toshas commited on
Commit
5d17894
·
1 Parent(s): a5afa17

initial commit

Browse files
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ __pycache__
2
+ gradio_cached_examples
3
+ *.pyi
4
+ *.egg-info
LICENSE.txt ADDED
@@ -0,0 +1,427 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Attribution-ShareAlike 4.0 International
2
+
3
+ =======================================================================
4
+
5
+ Creative Commons Corporation ("Creative Commons") is not a law firm and
6
+ does not provide legal services or legal advice. Distribution of
7
+ Creative Commons public licenses does not create a lawyer-client or
8
+ other relationship. Creative Commons makes its licenses and related
9
+ information available on an "as-is" basis. Creative Commons gives no
10
+ warranties regarding its licenses, any material licensed under their
11
+ terms and conditions, or any related information. Creative Commons
12
+ disclaims all liability for damages resulting from their use to the
13
+ fullest extent possible.
14
+
15
+ Using Creative Commons Public Licenses
16
+
17
+ Creative Commons public licenses provide a standard set of terms and
18
+ conditions that creators and other rights holders may use to share
19
+ original works of authorship and other material subject to copyright
20
+ and certain other rights specified in the public license below. The
21
+ following considerations are for informational purposes only, are not
22
+ exhaustive, and do not form part of our licenses.
23
+
24
+ Considerations for licensors: Our public licenses are
25
+ intended for use by those authorized to give the public
26
+ permission to use material in ways otherwise restricted by
27
+ copyright and certain other rights. Our licenses are
28
+ irrevocable. Licensors should read and understand the terms
29
+ and conditions of the license they choose before applying it.
30
+ Licensors should also secure all rights necessary before
31
+ applying our licenses so that the public can reuse the
32
+ material as expected. Licensors should clearly mark any
33
+ material not subject to the license. This includes other CC-
34
+ licensed material, or material used under an exception or
35
+ limitation to copyright. More considerations for licensors:
36
+ wiki.creativecommons.org/Considerations_for_licensors
37
+
38
+ Considerations for the public: By using one of our public
39
+ licenses, a licensor grants the public permission to use the
40
+ licensed material under specified terms and conditions. If
41
+ the licensor's permission is not necessary for any reason--for
42
+ example, because of any applicable exception or limitation to
43
+ copyright--then that use is not regulated by the license. Our
44
+ licenses grant only permissions under copyright and certain
45
+ other rights that a licensor has authority to grant. Use of
46
+ the licensed material may still be restricted for other
47
+ reasons, including because others have copyright or other
48
+ rights in the material. A licensor may make special requests,
49
+ such as asking that all changes be marked or described.
50
+ Although not required by our licenses, you are encouraged to
51
+ respect those requests where reasonable. More considerations
52
+ for the public:
53
+ wiki.creativecommons.org/Considerations_for_licensees
54
+
55
+ =======================================================================
56
+
57
+ Creative Commons Attribution-ShareAlike 4.0 International Public
58
+ License
59
+
60
+ By exercising the Licensed Rights (defined below), You accept and agree
61
+ to be bound by the terms and conditions of this Creative Commons
62
+ Attribution-ShareAlike 4.0 International Public License ("Public
63
+ License"). To the extent this Public License may be interpreted as a
64
+ contract, You are granted the Licensed Rights in consideration of Your
65
+ acceptance of these terms and conditions, and the Licensor grants You
66
+ such rights in consideration of benefits the Licensor receives from
67
+ making the Licensed Material available under these terms and
68
+ conditions.
69
+
70
+
71
+ Section 1 -- Definitions.
72
+
73
+ a. Adapted Material means material subject to Copyright and Similar
74
+ Rights that is derived from or based upon the Licensed Material
75
+ and in which the Licensed Material is translated, altered,
76
+ arranged, transformed, or otherwise modified in a manner requiring
77
+ permission under the Copyright and Similar Rights held by the
78
+ Licensor. For purposes of this Public License, where the Licensed
79
+ Material is a musical work, performance, or sound recording,
80
+ Adapted Material is always produced where the Licensed Material is
81
+ synched in timed relation with a moving image.
82
+
83
+ b. Adapter's License means the license You apply to Your Copyright
84
+ and Similar Rights in Your contributions to Adapted Material in
85
+ accordance with the terms and conditions of this Public License.
86
+
87
+ c. BY-SA Compatible License means a license listed at
88
+ creativecommons.org/compatiblelicenses, approved by Creative
89
+ Commons as essentially the equivalent of this Public License.
90
+
91
+ d. Copyright and Similar Rights means copyright and/or similar rights
92
+ closely related to copyright including, without limitation,
93
+ performance, broadcast, sound recording, and Sui Generis Database
94
+ Rights, without regard to how the rights are labeled or
95
+ categorized. For purposes of this Public License, the rights
96
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
97
+ Rights.
98
+
99
+ e. Effective Technological Measures means those measures that, in the
100
+ absence of proper authority, may not be circumvented under laws
101
+ fulfilling obligations under Article 11 of the WIPO Copyright
102
+ Treaty adopted on December 20, 1996, and/or similar international
103
+ agreements.
104
+
105
+ f. Exceptions and Limitations means fair use, fair dealing, and/or
106
+ any other exception or limitation to Copyright and Similar Rights
107
+ that applies to Your use of the Licensed Material.
108
+
109
+ g. License Elements means the license attributes listed in the name
110
+ of a Creative Commons Public License. The License Elements of this
111
+ Public License are Attribution and ShareAlike.
112
+
113
+ h. Licensed Material means the artistic or literary work, database,
114
+ or other material to which the Licensor applied this Public
115
+ License.
116
+
117
+ i. Licensed Rights means the rights granted to You subject to the
118
+ terms and conditions of this Public License, which are limited to
119
+ all Copyright and Similar Rights that apply to Your use of the
120
+ Licensed Material and that the Licensor has authority to license.
121
+
122
+ j. Licensor means the individual(s) or entity(ies) granting rights
123
+ under this Public License.
124
+
125
+ k. Share means to provide material to the public by any means or
126
+ process that requires permission under the Licensed Rights, such
127
+ as reproduction, public display, public performance, distribution,
128
+ dissemination, communication, or importation, and to make material
129
+ available to the public including in ways that members of the
130
+ public may access the material from a place and at a time
131
+ individually chosen by them.
132
+
133
+ l. Sui Generis Database Rights means rights other than copyright
134
+ resulting from Directive 96/9/EC of the European Parliament and of
135
+ the Council of 11 March 1996 on the legal protection of databases,
136
+ as amended and/or succeeded, as well as other essentially
137
+ equivalent rights anywhere in the world.
138
+
139
+ m. You means the individual or entity exercising the Licensed Rights
140
+ under this Public License. Your has a corresponding meaning.
141
+
142
+
143
+ Section 2 -- Scope.
144
+
145
+ a. License grant.
146
+
147
+ 1. Subject to the terms and conditions of this Public License,
148
+ the Licensor hereby grants You a worldwide, royalty-free,
149
+ non-sublicensable, non-exclusive, irrevocable license to
150
+ exercise the Licensed Rights in the Licensed Material to:
151
+
152
+ a. reproduce and Share the Licensed Material, in whole or
153
+ in part; and
154
+
155
+ b. produce, reproduce, and Share Adapted Material.
156
+
157
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
158
+ Exceptions and Limitations apply to Your use, this Public
159
+ License does not apply, and You do not need to comply with
160
+ its terms and conditions.
161
+
162
+ 3. Term. The term of this Public License is specified in Section
163
+ 6(a).
164
+
165
+ 4. Media and formats; technical modifications allowed. The
166
+ Licensor authorizes You to exercise the Licensed Rights in
167
+ all media and formats whether now known or hereafter created,
168
+ and to make technical modifications necessary to do so. The
169
+ Licensor waives and/or agrees not to assert any right or
170
+ authority to forbid You from making technical modifications
171
+ necessary to exercise the Licensed Rights, including
172
+ technical modifications necessary to circumvent Effective
173
+ Technological Measures. For purposes of this Public License,
174
+ simply making modifications authorized by this Section 2(a)
175
+ (4) never produces Adapted Material.
176
+
177
+ 5. Downstream recipients.
178
+
179
+ a. Offer from the Licensor -- Licensed Material. Every
180
+ recipient of the Licensed Material automatically
181
+ receives an offer from the Licensor to exercise the
182
+ Licensed Rights under the terms and conditions of this
183
+ Public License.
184
+
185
+ b. Additional offer from the Licensor -- Adapted Material.
186
+ Every recipient of Adapted Material from You
187
+ automatically receives an offer from the Licensor to
188
+ exercise the Licensed Rights in the Adapted Material
189
+ under the conditions of the Adapter's License You apply.
190
+
191
+ c. No downstream restrictions. You may not offer or impose
192
+ any additional or different terms or conditions on, or
193
+ apply any Effective Technological Measures to, the
194
+ Licensed Material if doing so restricts exercise of the
195
+ Licensed Rights by any recipient of the Licensed
196
+ Material.
197
+
198
+ 6. No endorsement. Nothing in this Public License constitutes or
199
+ may be construed as permission to assert or imply that You
200
+ are, or that Your use of the Licensed Material is, connected
201
+ with, or sponsored, endorsed, or granted official status by,
202
+ the Licensor or others designated to receive attribution as
203
+ provided in Section 3(a)(1)(A)(i).
204
+
205
+ b. Other rights.
206
+
207
+ 1. Moral rights, such as the right of integrity, are not
208
+ licensed under this Public License, nor are publicity,
209
+ privacy, and/or other similar personality rights; however, to
210
+ the extent possible, the Licensor waives and/or agrees not to
211
+ assert any such rights held by the Licensor to the limited
212
+ extent necessary to allow You to exercise the Licensed
213
+ Rights, but not otherwise.
214
+
215
+ 2. Patent and trademark rights are not licensed under this
216
+ Public License.
217
+
218
+ 3. To the extent possible, the Licensor waives any right to
219
+ collect royalties from You for the exercise of the Licensed
220
+ Rights, whether directly or through a collecting society
221
+ under any voluntary or waivable statutory or compulsory
222
+ licensing scheme. In all other cases the Licensor expressly
223
+ reserves any right to collect such royalties.
224
+
225
+
226
+ Section 3 -- License Conditions.
227
+
228
+ Your exercise of the Licensed Rights is expressly made subject to the
229
+ following conditions.
230
+
231
+ a. Attribution.
232
+
233
+ 1. If You Share the Licensed Material (including in modified
234
+ form), You must:
235
+
236
+ a. retain the following if it is supplied by the Licensor
237
+ with the Licensed Material:
238
+
239
+ i. identification of the creator(s) of the Licensed
240
+ Material and any others designated to receive
241
+ attribution, in any reasonable manner requested by
242
+ the Licensor (including by pseudonym if
243
+ designated);
244
+
245
+ ii. a copyright notice;
246
+
247
+ iii. a notice that refers to this Public License;
248
+
249
+ iv. a notice that refers to the disclaimer of
250
+ warranties;
251
+
252
+ v. a URI or hyperlink to the Licensed Material to the
253
+ extent reasonably practicable;
254
+
255
+ b. indicate if You modified the Licensed Material and
256
+ retain an indication of any previous modifications; and
257
+
258
+ c. indicate the Licensed Material is licensed under this
259
+ Public License, and include the text of, or the URI or
260
+ hyperlink to, this Public License.
261
+
262
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
263
+ reasonable manner based on the medium, means, and context in
264
+ which You Share the Licensed Material. For example, it may be
265
+ reasonable to satisfy the conditions by providing a URI or
266
+ hyperlink to a resource that includes the required
267
+ information.
268
+
269
+ 3. If requested by the Licensor, You must remove any of the
270
+ information required by Section 3(a)(1)(A) to the extent
271
+ reasonably practicable.
272
+
273
+ b. ShareAlike.
274
+
275
+ In addition to the conditions in Section 3(a), if You Share
276
+ Adapted Material You produce, the following conditions also apply.
277
+
278
+ 1. The Adapter's License You apply must be a Creative Commons
279
+ license with the same License Elements, this version or
280
+ later, or a BY-SA Compatible License.
281
+
282
+ 2. You must include the text of, or the URI or hyperlink to, the
283
+ Adapter's License You apply. You may satisfy this condition
284
+ in any reasonable manner based on the medium, means, and
285
+ context in which You Share Adapted Material.
286
+
287
+ 3. You may not offer or impose any additional or different terms
288
+ or conditions on, or apply any Effective Technological
289
+ Measures to, Adapted Material that restrict exercise of the
290
+ rights granted under the Adapter's License You apply.
291
+
292
+
293
+ Section 4 -- Sui Generis Database Rights.
294
+
295
+ Where the Licensed Rights include Sui Generis Database Rights that
296
+ apply to Your use of the Licensed Material:
297
+
298
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
299
+ to extract, reuse, reproduce, and Share all or a substantial
300
+ portion of the contents of the database;
301
+
302
+ b. if You include all or a substantial portion of the database
303
+ contents in a database in which You have Sui Generis Database
304
+ Rights, then the database in which You have Sui Generis Database
305
+ Rights (but not its individual contents) is Adapted Material,
306
+ including for purposes of Section 3(b); and
307
+
308
+ c. You must comply with the conditions in Section 3(a) if You Share
309
+ all or a substantial portion of the contents of the database.
310
+
311
+ For the avoidance of doubt, this Section 4 supplements and does not
312
+ replace Your obligations under this Public License where the Licensed
313
+ Rights include other Copyright and Similar Rights.
314
+
315
+
316
+ Section 5 -- Disclaimer of Warranties and Limitation of Liability.
317
+
318
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
319
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
320
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
321
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
322
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
323
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
324
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
325
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
326
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
327
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
328
+
329
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
330
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
331
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
332
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
333
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
334
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
335
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
336
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
337
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
338
+
339
+ c. The disclaimer of warranties and limitation of liability provided
340
+ above shall be interpreted in a manner that, to the extent
341
+ possible, most closely approximates an absolute disclaimer and
342
+ waiver of all liability.
343
+
344
+
345
+ Section 6 -- Term and Termination.
346
+
347
+ a. This Public License applies for the term of the Copyright and
348
+ Similar Rights licensed here. However, if You fail to comply with
349
+ this Public License, then Your rights under this Public License
350
+ terminate automatically.
351
+
352
+ b. Where Your right to use the Licensed Material has terminated under
353
+ Section 6(a), it reinstates:
354
+
355
+ 1. automatically as of the date the violation is cured, provided
356
+ it is cured within 30 days of Your discovery of the
357
+ violation; or
358
+
359
+ 2. upon express reinstatement by the Licensor.
360
+
361
+ For the avoidance of doubt, this Section 6(b) does not affect any
362
+ right the Licensor may have to seek remedies for Your violations
363
+ of this Public License.
364
+
365
+ c. For the avoidance of doubt, the Licensor may also offer the
366
+ Licensed Material under separate terms or conditions or stop
367
+ distributing the Licensed Material at any time; however, doing so
368
+ will not terminate this Public License.
369
+
370
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
371
+ License.
372
+
373
+
374
+ Section 7 -- Other Terms and Conditions.
375
+
376
+ a. The Licensor shall not be bound by any additional or different
377
+ terms or conditions communicated by You unless expressly agreed.
378
+
379
+ b. Any arrangements, understandings, or agreements regarding the
380
+ Licensed Material not stated herein are separate from and
381
+ independent of the terms and conditions of this Public License.
382
+
383
+
384
+ Section 8 -- Interpretation.
385
+
386
+ a. For the avoidance of doubt, this Public License does not, and
387
+ shall not be interpreted to, reduce, limit, restrict, or impose
388
+ conditions on any use of the Licensed Material that could lawfully
389
+ be made without permission under this Public License.
390
+
391
+ b. To the extent possible, if any provision of this Public License is
392
+ deemed unenforceable, it shall be automatically reformed to the
393
+ minimum extent necessary to make it enforceable. If the provision
394
+ cannot be reformed, it shall be severed from this Public License
395
+ without affecting the enforceability of the remaining terms and
396
+ conditions.
397
+
398
+ c. No term or condition of this Public License will be waived and no
399
+ failure to comply consented to unless expressly agreed to by the
400
+ Licensor.
401
+
402
+ d. Nothing in this Public License constitutes or may be interpreted
403
+ as a limitation upon, or waiver of, any privileges and immunities
404
+ that apply to the Licensor or You, including from the legal
405
+ processes of any jurisdiction or authority.
406
+
407
+
408
+ =======================================================================
409
+
410
+ Creative Commons is not a party to its public
411
+ licenses. Notwithstanding, Creative Commons may elect to apply one of
412
+ its public licenses to material it publishes and in those instances
413
+ will be considered the “Licensor.” The text of the Creative Commons
414
+ public licenses is dedicated to the public domain under the CC0 Public
415
+ Domain Dedication. Except for the limited purpose of indicating that
416
+ material is shared under a Creative Commons public license or as
417
+ otherwise permitted by the Creative Commons policies published at
418
+ creativecommons.org/policies, Creative Commons does not authorize the
419
+ use of the trademark "Creative Commons" or any other trademark or logo
420
+ of Creative Commons without its prior written consent including,
421
+ without limitation, in connection with any unauthorized modifications
422
+ to any of its public licenses or any other arrangements,
423
+ understandings, or agreements concerning use of licensed material. For
424
+ the avoidance of doubt, this paragraph does not form part of the
425
+ public licenses.
426
+
427
+ Creative Commons may be contacted at creativecommons.org.
MANIFEST.in ADDED
@@ -0,0 +1 @@
 
 
1
+ recursive-include gradio_dualvision/gradio_patches/templates *
README.md ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Gradio DualVision Demo
3
+ emoji: 👀
4
+ colorFrom: blue
5
+ colorTo: red
6
+ sdk: gradio
7
+ sdk_version: 4.44.1
8
+ app_file: app.py
9
+ pinned: true
10
+ license: cc-by-sa-4.0
11
+ ---
12
+ #### This thing ☝️ is metadata required at the top of README.md for hosting this exact repository as a Hugging Face Space 🤗.
13
+
14
+ # Gradio DualVision
15
+
16
+ [![Hugging Face Space](https://img.shields.io/badge/🤗%20Hugging%20Face%20-Space-yellow)](https://huggingface.co/spaces/toshas/gradio-dualvision)
17
+
18
+ DualVision is a Gradio template app for image processing. It was developed
19
+ to support the [Marigold](https://marigoldcomputervision.github.io) project. The app features:
20
+ - A web interface, powered by [Gradio](www.gradio.app) and [gradio-imageslider](https://github.com/pngwn/gradio-imageslider).
21
+ - Compatibility with desktop and mobile browsers.
22
+ - Native integration with Hugging Face Spaces.
23
+ - GPU support in the backend, including Hugging Face [ZeroGPU](https://huggingface.co/docs/hub/spaces-zerogpu).
24
+ - Easily upload input images, including from the camera roll.
25
+ - Easily add configurable settings and see their effect instantly.
26
+ - Instant processing and side-by-side inspection.
27
+ - Multi-modal prediction: as it often happens, your algorithm can produce multiple images.
28
+ - Radio-buttons for easy switch between the inputs and produced outputs.
29
+ - A built-in examples gallery for a smoother user experience.
30
+
31
+ ## Live demo
32
+
33
+ YouTube video:<br>
34
+ [![YouTube](http://i.ytimg.com/vi/8j0X8qXfKCg/hqdefault.jpg)](https://www.youtube.com/watch?v=8j0X8qXfKCg)
35
+
36
+ This very space running live on Hugging Face Spaces:
37
+ <a href="https://huggingface.co/spaces/toshas/gradio-dualvision" style="position: relative; top: 2px;"><img src="https://img.shields.io/badge/🤗%20Hugging%20Face-Space-yellow" height="16"></a>
38
+
39
+ A few real examples:
40
+ - [Marigold Depth](https://huggingface.co/spaces/prs-eth/marigold)
41
+
42
+ ## Quick start
43
+
44
+ Check out the template image processing [app.py](app.py); copy it and start modifying!
45
+
46
+ 1. Install as a python package: `pip install git+https://github.com/toshas/gradio-dualvision.git`.
47
+ 2. Create an `app.py` file.
48
+ 3. Import and subclass from `DualVisionApp`.
49
+ 4. Implement `build_user_components` and `process` methods, and optionally `make_header`.
50
+ 5. Launch the app!
51
+
52
+ ## DualVisionApp API
53
+
54
+ - `title`: Title of the application (str, required).
55
+ - `examples_path`: Base path where examples will be searched (Default: `"examples"`).
56
+ - `examples_per_page`: How many examples to show at the bottom of the app (Default: `12`).
57
+ - `examples_cache`: Examples caching policy, corresponding to `cache_examples` argument of gradio.Examples (Default: `"lazy"`).
58
+ - `squeeze_canvas`: When True, the image is fit to the browser viewport. When False, the image is fit to width (Default: `True`).
59
+ - `squeeze_viewport_height_pct`: Percentage of the browser viewport height (Default: `75`).
60
+ - `left_selector_visible`: Whether controls for changing modalities in the left part of the slider are visible (Default: `False`).
61
+ - `advanced_settings_can_be_half_width`: Whether allow placing advanced settings dropdown in half-column space whenever possible (Default: `True`).
62
+ - `key_original_image`: Name of the key under which the input image is shown in the modality selectors (Default: `"Original"`).
63
+ - `spaces_zero_gpu_enabled`: When True, the app wraps the processing function with the ZeroGPU decorator.
64
+ - `spaces_zero_gpu_duration`: Defines an integer duration in seconds passed into the ZeroGPU decorator.
65
+ - `slider_position`: Position of the slider between 0 and 1 (Default: `0.5`).
66
+ - `slider_line_color`: Color of the slider line (Default: `"#FFF"`).
67
+ - `slider_line_width`: Width of the slider line (Default: `"4px"`).
68
+ - `slider_arrows_color`: Color of the slider arrows (Default: `"#FFF"`).
69
+ - `slider_arrows_width`: Width of the slider arrows (Default: `2px`).
70
+ - `gallery_thumb_min_size`: Min size of the gallery thumbnail (Default: `96px`).
71
+ - `**kwargs`: Any other arguments that Gradio Blocks class can take.
72
+
73
+ **NB**: when setting `spaces_zero_gpu_enabled=True`, it may be required to add `import spaces` at the top of the app.py to
74
+ avoid the `RuntimeError` with "CUDA has been initialized before importing the `spaces` package".
75
+
76
+ ## Real talk
77
+
78
+ **Q: What is the idea behind this template?**<br>
79
+ A: Processing an image with various settings, inspecting multiple outputs side-by-side, and deploying such a demo with
80
+ readily-accessible examples is a common pattern in computer vision and image processing. This template extends upon
81
+ the [gradio-imageslider](https://github.com/pngwn/gradio-imageslider) custom component, adds modality selectors (radio
82
+ buttons), and connects it all nicely with the Gradio's built-in Examples functionality.
83
+
84
+ **Q: Isn't it exactly what `gradio-imageslider` is doing?**<br>
85
+ A: Not quite. See the [gradio_dualvision/gradio_patches](gradio_dualvision/gradio_patches) directory for a complete set
86
+ of version-specific changes required to wire it all up _nicely_. Indeed, a custom component with all these functions
87
+ would be more efficient.
88
+
89
+ **Q: What is the architecture of the template?**<br>
90
+ - Inputs: an input image (that is either uploaded or sent from Examples), and any settings you create in the
91
+ `build_user_components` override.
92
+ - Outputs: a dictionary of `PIL.Image`s produced by your `process` function override, subsets of which you want to
93
+ inspect side-by-side in the Slider.
94
+ - State: a hidden `gradio.Gallery` component that stores all the output modalities from your `process` override.
95
+ - Selectors: `gradio.Radio` buttons, which react to clicks and send requested images from the State to the Slider.
96
+ - Slider: `gradio-imageslider` custom component that allows using the slider to reveal parts of the images.
97
+ - Examples: `gradio.Examples` component that displays a gallery of example images, processes them upon the first click,
98
+ and caches the result for next users.
99
+
100
+ **Q: What are the conventions for `build_user_components` and `process` overrides?**<br>
101
+ - `build_user_components` defines `gradio` components and their layout, which will be visible in the "Advanced Settings"
102
+ dropdown under the Slider component.
103
+ - Each such component will have a default value; it is possible to either hardcode it, or use a class variable, as it
104
+ will be needed again in the `process` function (for example, define it as `self.DEFAULT_SETTING_VALUE`).
105
+ - Associate a string with each created setting (for example, `"setting_name"`) that you want to pass around and output
106
+ a dictionary of them.
107
+ - `process` takes an image and `**kwargs`, which may or may not contain the settings of interest.
108
+ - To resolve a setting, use `kwargs.get("setting_name", self.DEFAULT_SETTING_VALUE)` in order to fall back to the
109
+ initial value of this setting.
110
+ - This way, default settings will be applied only to Example images that did not have _custom example settings_.
111
+
112
+ **Q: How do I specify custom default arguments for an example image?**<br>
113
+ A: Just create a file called `<path_to_image>.settings.json` and populate it with the custom settings for this sample -
114
+ they will take precedence over the global default settings.
115
+
116
+ **Q: How do I modify the app header?**<br>
117
+ A: Override the `make_header` method and use `gradio.HTML` or `gradio.Markdown` to customize the header.
118
+
119
+ **Q: What's up with the Example cats?**<br>
120
+ These are the cats of the Marigold authors!
121
+
122
+ ## Limitations
123
+
124
+ - Does not work correctly inside the `TabbedInterface`.
125
+ - Double copying between the hidden gallery component and the slider introduces visible flickering.
126
+ - Fixed versions of `gradio==4.44.1` and `gradio_imageslider==0.0.20`;
127
+ PRs are welcome but should start as a discussion in the [Issues](https://github.com/toshas/gradio-dualvision/issues)
128
+ first.
129
+
130
+ ## Citation:
131
+ If you find this code useful, we kindly ask you to cite our papers:
132
+ ```
133
+ @InProceedings{ke2023repurposing,
134
+ title={Repurposing Diffusion-Based Image Generators for Monocular Depth Estimation},
135
+ author={Bingxin Ke and Anton Obukhov and Shengyu Huang and Nando Metzger and Rodrigo Caye Daudt and Konrad Schindler},
136
+ booktitle = {Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
137
+ year={2024}
138
+ }
139
+ ```
140
+
141
+ ## License
142
+
143
+ [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)
app.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing, developed to
6
+ # support the Marigold project: https://marigoldcomputervision.github.io
7
+
8
+ import gradio as gr
9
+ from PIL import Image, ImageFilter
10
+
11
+ from gradio_dualvision import DualVisionApp
12
+
13
+
14
+ class ImageFiltersApp(DualVisionApp):
15
+ DEFAULT_FILTER_SIZE = 15
16
+
17
+ def make_header(self):
18
+ """
19
+ Create a header section with Markdown and HTML.
20
+ """
21
+ gr.Markdown(
22
+ f"""
23
+ ## {self.title}
24
+ <p align="center">
25
+ <a title="Github" href="https://github.com/toshas/gradio-dualvision" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
26
+ <img src="https://img.shields.io/github/stars/toshas/gradio-dualvision?label=GitHub%20%E2%98%85&logo=github&color=C8C" alt="badge-github-stars">
27
+ </a>
28
+ <a title="Social" href="https://twitter.com/antonobukhov1" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
29
+ <img src="https://shields.io/twitter/follow/:?label=Subscribe%20for%20updates!" alt="social">
30
+ </a>
31
+ </p>
32
+ <p align="center" style="margin-top: 0px;">
33
+ Upload a photo or select an example to process the input in real time.
34
+ Use the slider to reveal areas of interest.
35
+ Use the radio-buttons to switch between modalities.
36
+ </p>
37
+ """
38
+ )
39
+
40
+ def build_user_components(self):
41
+ """
42
+ Create gradio components for the Advanced Settings dropdown, that will be passed into the `process` method.
43
+ Use gr.Row(), gr.Column(), and other context managers to arrange the components. Return them as a flat dict.
44
+ """
45
+ filter_size = gr.Slider(
46
+ minimum=1,
47
+ maximum=51,
48
+ value=self.DEFAULT_FILTER_SIZE,
49
+ step=2,
50
+ label="Filter size",
51
+ )
52
+ return {
53
+ "filter_size": filter_size,
54
+ }
55
+
56
+ def process(self, image_in: Image.Image, **kwargs):
57
+ """
58
+ Process an input image into multiple modalities using the provided arguments or default settings.
59
+ Returns two dictionaries: one containing the modalities and another with the actual settings.
60
+ """
61
+ filter_size = kwargs.get("filter_size", self.DEFAULT_FILTER_SIZE)
62
+
63
+ image_out_gray = image_in.convert("L")
64
+ image_out_gaussian = image_in.filter(ImageFilter.GaussianBlur(filter_size // 2))
65
+ image_out_median = image_in.filter(ImageFilter.MedianFilter(filter_size))
66
+
67
+ out_modalities = {
68
+ "Gray": image_out_gray,
69
+ "Gaussian": image_out_gaussian,
70
+ "Median": image_out_median,
71
+ }
72
+ out_settings = {
73
+ "filter_size": filter_size,
74
+ }
75
+ return out_modalities, out_settings
76
+
77
+
78
+ with ImageFiltersApp(
79
+ title="Gradio DualVision",
80
+ examples_path="examples",
81
+ examples_per_page=5,
82
+ squeeze_canvas=True,
83
+ ) as demo:
84
+ demo.queue(
85
+ api_open=False,
86
+ ).launch(
87
+ server_name="0.0.0.0",
88
+ server_port=7860,
89
+ )
examples/cat1.jpg ADDED

Git LFS Details

  • SHA256: 878418435bd3c5b19d1796770379a7bf862e0e7b09649ff139527e21446ed80a
  • Pointer size: 130 Bytes
  • Size of remote file: 59.1 kB
examples/cat1.jpg.settings.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "filter_size": 11
3
+ }
examples/cat2.jpg ADDED

Git LFS Details

  • SHA256: 562cf7ee4616c537654e485460a60286b1fb7801ee0ccda051b9b19f8052d29e
  • Pointer size: 131 Bytes
  • Size of remote file: 120 kB
examples/cat3.jpg ADDED

Git LFS Details

  • SHA256: ce08dc032339d167844fc7219c564c84ef1f0cef5dea463d8c1db0b705c7eca9
  • Pointer size: 130 Bytes
  • Size of remote file: 49.1 kB
gradio_dualvision/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing. It was developed
6
+ # to support the Marigold project. If you find this code useful, we kindly
7
+ # ask you to cite our most relevant papers.
8
+ # More information about Marigold:
9
+ # https://marigoldmonodepth.github.io
10
+ # https://marigoldcomputervision.github.io
11
+ # Efficient inference pipelines are now part of diffusers:
12
+ # https://huggingface.co/docs/diffusers/using-diffusers/marigold_usage
13
+ # https://huggingface.co/docs/diffusers/api/pipelines/marigold
14
+ # Examples of trained models and live demos:
15
+ # https://huggingface.co/prs-eth
16
+ # Related projects:
17
+ # https://marigolddepthcompletion.github.io/
18
+ # https://rollingdepth.github.io/
19
+ # Citation (BibTeX):
20
+ # https://github.com/prs-eth/Marigold#-citation
21
+ # https://github.com/prs-eth/Marigold-DC#-citation
22
+ # https://github.com/prs-eth/rollingdepth#-citation
23
+ # --------------------------------------------------------------------------
24
+
25
+ from .version import __version__
26
+ from .app_template import DualVisionApp
gradio_dualvision/app_template.py ADDED
@@ -0,0 +1,605 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing. It was developed
6
+ # to support the Marigold project. If you find this code useful, we kindly
7
+ # ask you to cite our most relevant papers.
8
+ # More information about Marigold:
9
+ # https://marigoldmonodepth.github.io
10
+ # https://marigoldcomputervision.github.io
11
+ # Efficient inference pipelines are now part of diffusers:
12
+ # https://huggingface.co/docs/diffusers/using-diffusers/marigold_usage
13
+ # https://huggingface.co/docs/diffusers/api/pipelines/marigold
14
+ # Examples of trained models and live demos:
15
+ # https://huggingface.co/prs-eth
16
+ # Related projects:
17
+ # https://marigolddepthcompletion.github.io/
18
+ # https://rollingdepth.github.io/
19
+ # Citation (BibTeX):
20
+ # https://github.com/prs-eth/Marigold#-citation
21
+ # https://github.com/prs-eth/Marigold-DC#-citation
22
+ # https://github.com/prs-eth/rollingdepth#-citation
23
+ # --------------------------------------------------------------------------
24
+ import glob
25
+ import json
26
+ import os
27
+ import re
28
+
29
+ import gradio as gr
30
+ import spaces
31
+ from PIL import Image
32
+ from gradio.components.base import Component
33
+
34
+ from .gradio_patches.examples import Examples
35
+ from .gradio_patches.imagesliderplus import ImageSliderPlus
36
+ from .gradio_patches.radio import Radio
37
+
38
+
39
+ class DualVisionApp(gr.Blocks):
40
+ def __init__(
41
+ self,
42
+ title,
43
+ examples_path="examples",
44
+ examples_per_page=12,
45
+ examples_cache="lazy",
46
+ squeeze_canvas=True,
47
+ squeeze_viewport_height_pct=75,
48
+ left_selector_visible=False,
49
+ advanced_settings_can_be_half_width=True,
50
+ key_original_image="Original",
51
+ spaces_zero_gpu_enabled=False,
52
+ spaces_zero_gpu_duration=None,
53
+ slider_position=0.5,
54
+ slider_line_color="#FFF",
55
+ slider_line_width="4px",
56
+ slider_arrows_color="#FFF",
57
+ slider_arrows_width="2px",
58
+ gallery_thumb_min_size="96px",
59
+ **kwargs,
60
+ ):
61
+ """
62
+ A wrapper around Gradio Blocks class that implements an image processing demo template. All the user has to do
63
+ is to subclass this class and implement two methods: `process` implementing the image processing, and
64
+ `build_user_components` implementing Gradio components reading the additional processing arguments.
65
+ Args:
66
+ title: Title of the application (str, required).
67
+ examples_path: Base path where examples will be searched (Default: `"examples"`).
68
+ examples_per_page: How many examples to show at the bottom of the app (Default: `12`).
69
+ examples_cache: Examples caching policy, corresponding to `cache_examples` argument of gradio.Examples (Default: `"lazy"`).
70
+ squeeze_canvas: When True, the image is fit to the browser viewport. When False, the image is fit to width (Default: `True`).
71
+ squeeze_viewport_height_pct: Percentage of the browser viewport height (Default: `75`).
72
+ left_selector_visible: Whether controls for changing modalities in the left part of the slider are visible (Default: `False`).
73
+ key_original_image: Name of the key under which the input image is shown in the modality selectors (Default: `"Original"`).
74
+ advanced_settings_can_be_half_width: Whether allow placing advanced settings dropdown in half-column space whenever possible (Default: `True`).
75
+ spaces_zero_gpu_enabled: When True, the app wraps the processing function with the ZeroGPU decorator.
76
+ spaces_zero_gpu_duration: Defines an integer duration in seconds passed into the ZeroGPU decorator.
77
+ slider_position: Position of the slider between 0 and 1 (Default: `0.5`).
78
+ slider_line_color: Color of the slider line (Default: `"#FFF"`).
79
+ slider_line_width: Width of the slider line (Default: `"4px"`).
80
+ slider_arrows_color: Color of the slider arrows (Default: `"#FFF"`).
81
+ slider_arrows_width: Width of the slider arrows (Default: `2px`).
82
+ gallery_thumb_min_size: Min size of the gallery thumbnail (Default: `96px`).
83
+ **kwargs: Any other arguments that Gradio Blocks class can take.
84
+ """
85
+ squeeze_viewport_height_pct = int(squeeze_viewport_height_pct)
86
+ if not 50 <= squeeze_viewport_height_pct <= 100:
87
+ raise gr.Error(
88
+ "`squeeze_viewport_height_pct` should be an integer between 50 and 100."
89
+ )
90
+ if not os.path.isdir(examples_path):
91
+ raise gr.Error("`examples_path` should be a directory.")
92
+ if not 0 <= slider_position <= 1:
93
+ raise gr.Error("`slider_position` should be between 0 and 1.")
94
+ kwargs = {k: v for k, v in kwargs.items()}
95
+ kwargs["title"] = title
96
+ self.examples_path = examples_path
97
+ self.examples_per_page = examples_per_page
98
+ self.examples_cache = examples_cache
99
+ self.key_original_image = key_original_image
100
+ self.slider_position = slider_position
101
+ self.input_keys = None
102
+ self.left_selector_visible = left_selector_visible
103
+ self.advanced_settings_can_be_half_width = advanced_settings_can_be_half_width
104
+ if spaces_zero_gpu_enabled:
105
+ self.process_components = spaces.GPU(
106
+ self.process_components, duration=spaces_zero_gpu_duration
107
+ )
108
+ self.head = ""
109
+ self.head += """
110
+ <script>
111
+ let observerFooterButtons = new MutationObserver((mutationsList, observer) => {
112
+ const oldButtonLeft = document.querySelector(".show-api");
113
+ const oldButtonRight = document.querySelector(".built-with");
114
+ if (!oldButtonRight || !oldButtonLeft) {
115
+ return;
116
+ }
117
+ observer.disconnect();
118
+
119
+ const parentDiv = oldButtonLeft.parentNode;
120
+ if (!parentDiv) return;
121
+
122
+ const createButton = (referenceButton, text, href) => {
123
+ let newButton = referenceButton.cloneNode(true);
124
+ newButton.href = href;
125
+ newButton.textContent = text;
126
+ newButton.className = referenceButton.className;
127
+ newButton.style.textDecoration = "none";
128
+ newButton.style.display = "inline-block";
129
+ newButton.style.cursor = "pointer";
130
+ return newButton;
131
+ };
132
+
133
+ const newButton0 = createButton(oldButtonRight, "Built with Gradio DualVision", "https://github.com/toshas/gradio-dualvision");
134
+ const newButton1 = createButton(oldButtonRight, "Template by Anton Obukhov", "https://www.obukhov.ai");
135
+ const newButton2 = createButton(oldButtonRight, "Licensed under CC BY-SA 4.0", "http://creativecommons.org/licenses/by-sa/4.0/");
136
+
137
+ const separatorDiv = document.createElement("div");
138
+ separatorDiv.className = "svelte-1rjryqp";
139
+ separatorDiv.textContent = "·";
140
+
141
+ parentDiv.replaceChild(newButton0, oldButtonLeft);
142
+ parentDiv.replaceChild(newButton1, oldButtonRight);
143
+ parentDiv.appendChild(separatorDiv);
144
+ parentDiv.appendChild(newButton2);
145
+ });
146
+ observerFooterButtons.observe(document.body, { childList: true, subtree: true });
147
+ </script>
148
+ """
149
+ if kwargs.get("analytics_enabled") is not False:
150
+ self.head += f"""
151
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-1FWSVCGZTG"></script>
152
+ <script>
153
+ window.dataLayer = window.dataLayer || [];
154
+ function gtag() {{dataLayer.push(arguments);}}
155
+ gtag('js', new Date());
156
+ gtag('config', 'G-1FWSVCGZTG');
157
+ </script>
158
+ """
159
+ self.css = f"""
160
+ .sliderrow {{ /* center the slider */
161
+ display: flex;
162
+ justify-content: center;
163
+ }}
164
+ .slider {{ /* center the slider */
165
+ display: flex;
166
+ justify-content: center;
167
+ width: 100%;
168
+ }}
169
+ .slider .disabled {{ /* hide the main slider before image load */
170
+ visibility: hidden;
171
+ }}
172
+ .slider .svelte-9gxdi0 {{ /* hide the component label in the top-left corner before image load */
173
+ visibility: hidden;
174
+ }}
175
+ .slider .svelte-kzcjhc .icon-wrap {{
176
+ height: 0px; /* remove unnecessary spaces in captions before image load */
177
+ }}
178
+ .slider .svelte-kzcjhc.wrap {{
179
+ padding-top: 0px; /* remove unnecessary spaces in captions before image load */
180
+ }}
181
+ .slider .svelte-3w3rth {{ /* hide the dummy icon from the right pane before image load */
182
+ visibility: hidden;
183
+ }}
184
+ .slider .svelte-106mu0e a {{ /* hide the download button */
185
+ visibility: hidden;
186
+ }}
187
+ .slider .fixed {{ /* fix the opacity of the right pane image */
188
+ background-color: var(--anim-block-background-fill);
189
+ }}
190
+ .slider .inner {{ /* style slider line */
191
+ width: {slider_line_width};
192
+ background: {slider_line_color};
193
+ }}
194
+ .slider .icon-wrap svg {{ /* style slider arrows */
195
+ stroke: {slider_arrows_color};
196
+ stroke-width: {slider_arrows_width};
197
+ }}
198
+ .slider .icon-wrap path {{ /* style slider arrows */
199
+ fill: {slider_arrows_color};
200
+ }}
201
+ .row_reverse {{
202
+ flex-direction: row-reverse;
203
+ }}
204
+ .gallery.svelte-l4wpk0 {{ /* make examples gallery tiles square */
205
+ width: max({gallery_thumb_min_size}, calc(100vw / 8));
206
+ height: max({gallery_thumb_min_size}, calc(100vw / 8));
207
+ }}
208
+ .gallery.svelte-l4wpk0 img {{ /* make examples gallery tiles square */
209
+ width: max({gallery_thumb_min_size}, calc(100vw / 8));
210
+ height: max({gallery_thumb_min_size}, calc(100vw / 8));
211
+ }}
212
+ .gallery.svelte-l4wpk0 img {{ /* remove slider line from previews */
213
+ clip-path: inset(0 0 0 0);
214
+ }}
215
+ .gallery.svelte-l4wpk0 span {{ /* remove slider line from previews */
216
+ visibility: hidden;
217
+ }}
218
+ h1, h2, h3 {{ /* center markdown headings */
219
+ text-align: center;
220
+ display: block;
221
+ }}
222
+ """
223
+ if squeeze_canvas:
224
+ self.head += f"""
225
+ <script>
226
+ // fixes vertical size of the component when used inside of iframeResizer (on spaces)
227
+ function squeezeViewport() {{
228
+ if (typeof window.parentIFrame !== "undefined") {{
229
+ const images = document.querySelectorAll('.slider img');
230
+ window.parentIFrame.getPageInfo((info) => {{
231
+ const parentHeight = info.clientHeight;
232
+ images.forEach((img) => {{
233
+ img.style.maxHeight = `${{(parentHeight * {squeeze_viewport_height_pct}) / 100}}px`;
234
+ }});
235
+ }});
236
+ }}
237
+ }}
238
+ window.addEventListener('resize', squeezeViewport);
239
+
240
+ // fixes gradio-imageslider wrong position behavior when using fitting to content by triggering resize
241
+ let observerSlider = new MutationObserver((mutationsList, observer) => {{
242
+ let slider = document.querySelector(".slider");
243
+ if (!slider) {{
244
+ return;
245
+ }}
246
+ observer.disconnect();
247
+ let observerSliderImage = new MutationObserver((mutations) => {{
248
+ let img = slider.querySelector("img");
249
+ if (img && img.complete) {{
250
+ window.dispatchEvent(new Event('resize'));
251
+ }}
252
+ }});
253
+ observerSliderImage.observe(slider, {{ childList: true, subtree: true }});
254
+ }});
255
+ observerSlider.observe(document.body, {{ childList: true, subtree: true }});
256
+ </script>
257
+ """
258
+ self.css += f"""
259
+ .slider {{ /* make the slider dimensions fit to the uploaded content dimensions */
260
+ max-width: fit-content;
261
+ }}
262
+ .slider .half-wrap {{ /* make the empty component width almost full before image load */
263
+ width: 70vw;
264
+ }}
265
+ .slider img {{ /* Ensures image fits inside the viewport */
266
+ max-height: {squeeze_viewport_height_pct}vh;
267
+ }}
268
+ """
269
+ else:
270
+ self.css += f"""
271
+ .slider .half-wrap {{ /* make the upload area full width */
272
+ width: 100%;
273
+ }}
274
+ """
275
+ kwargs["css"] = kwargs.get("css", "") + self.css
276
+ kwargs["head"] = kwargs.get("head", "") + self.head
277
+ super().__init__(**kwargs)
278
+ with self:
279
+ self.make_interface()
280
+
281
+ def process(self, image_in: Image.Image, **kwargs):
282
+ """
283
+ Process an input image into multiple modalities using the provided arguments or default settings.
284
+ Returns two dictionaries: one containing the modalities and another with the actual settings.
285
+ Override this method in a subclass.
286
+ """
287
+ raise NotImplementedError("Please override the `process` method.")
288
+
289
+ def build_user_components(self):
290
+ """
291
+ Create gradio components for the Advanced Settings dropdown, that will be passed into the `process` method.
292
+ Use gr.Row(), gr.Column(), and other context managers to arrange the components. Return them as a flat dict.
293
+ Override this method in a subclass.
294
+ """
295
+ raise NotImplementedError("Please override the `build_user_components` method.")
296
+
297
+ def discover_examples(self):
298
+ """
299
+ Looks for valid image filenames.
300
+ """
301
+ pattern = re.compile(r".*\.(jpg|JPG|jpeg|JPEG|png|PNG)$")
302
+ paths = glob.glob(f"{self.examples_path}/*")
303
+ out = list(sorted(filter(pattern.match, paths)))
304
+ return out
305
+
306
+ def process_components(
307
+ self, image_in, modality_selector_left, modality_selector_right, **kwargs
308
+ ):
309
+ """
310
+ Wraps the call to `process`. Returns results in a structure used by the gallery, slider, radio components.
311
+ """
312
+ if image_in is None:
313
+ raise gr.Error("Input image is required")
314
+
315
+ image_settings = {}
316
+ if isinstance(image_in, str):
317
+ image_settings_path = image_in + ".settings.json"
318
+ if os.path.isfile(image_settings_path):
319
+ with open(image_settings_path, "r") as f:
320
+ image_settings = json.load(f)
321
+ image_in = Image.open(image_in).convert("RGB")
322
+ else:
323
+ if not isinstance(image_in, Image.Image):
324
+ raise gr.Error(f"Input must be a PIL image, got {type(image_in)}")
325
+ image_in = image_in.convert("RGB")
326
+ image_settings.update(kwargs)
327
+
328
+ results_dict, results_settings = self.process(image_in, **image_settings)
329
+
330
+ if not isinstance(results_dict, dict):
331
+ raise gr.Error(
332
+ f"`process` must return a dict[str, PIL.Image]. Got type: {type(results_dict)}"
333
+ )
334
+ if len(results_dict) == 0:
335
+ raise gr.Error("`process` did not return any modalities")
336
+ for k, v in results_dict.items():
337
+ if not isinstance(k, str):
338
+ raise gr.Error(
339
+ f"Output dict must have string keys. Found key of type {type(k)}: {repr(k)}"
340
+ )
341
+ if k == self.key_original_image:
342
+ raise gr.Error(
343
+ f"Output dict must not have an '{self.key_original_image}' key; it is reserved for the input"
344
+ )
345
+ if not isinstance(v, Image.Image):
346
+ raise gr.Error(
347
+ f"Value for key '{k}' must be a PIL Image, got type {type(v)}"
348
+ )
349
+ if len(results_settings) != len(self.input_keys):
350
+ raise gr.Error(
351
+ f"Expected number of settings ({len(self.input_keys)}), returned ({len(results_settings)})"
352
+ )
353
+ if any(k not in results_settings for k in self.input_keys):
354
+ raise gr.Error(f"Mismatching setgings keys")
355
+ results_settings = {k: results_settings[k] for k in self.input_keys}
356
+
357
+ results_dict = {
358
+ self.key_original_image: image_in,
359
+ **results_dict,
360
+ }
361
+
362
+ results_state = [[v, k] for k, v in results_dict.items()]
363
+ modalities = list(results_dict.keys())
364
+
365
+ modality_left = (
366
+ modality_selector_left
367
+ if modality_selector_left in modalities
368
+ else modalities[0]
369
+ )
370
+ modality_right = (
371
+ modality_selector_right
372
+ if modality_selector_right in modalities
373
+ else modalities[1]
374
+ )
375
+
376
+ return [
377
+ results_state, # goes to a gr.Gallery
378
+ [
379
+ results_dict[modality_left],
380
+ results_dict[modality_right],
381
+ ], # ImageSliderPlus
382
+ Radio(
383
+ choices=modalities,
384
+ value=modality_left,
385
+ label="Left",
386
+ key="Left",
387
+ ),
388
+ Radio(
389
+ choices=modalities if self.left_selector_visible else modalities[1:],
390
+ value=modality_right,
391
+ label="Right",
392
+ key="Right",
393
+ ),
394
+ *results_settings.values(),
395
+ ]
396
+
397
+ def on_process_first(
398
+ self,
399
+ image_slider,
400
+ modality_selector_left=None,
401
+ modality_selector_right=None,
402
+ *args,
403
+ ):
404
+ image_in = image_slider[0]
405
+ input_dict = {}
406
+ if len(args) > 0:
407
+ input_dict = {k: v for k, v in zip(self.input_keys, args)}
408
+ return self.process_components(
409
+ image_in, modality_selector_left, modality_selector_right, **input_dict
410
+ )
411
+
412
+ def on_process_subsequent(
413
+ self, results_state, modality_selector_left, modality_selector_right, *args
414
+ ):
415
+ if results_state is None:
416
+ raise gr.Error("Upload an image first or use an example below.")
417
+ results_state = {k: v for v, k in results_state}
418
+ image_in = results_state[self.key_original_image]
419
+ input_dict = {k: v for k, v in zip(self.input_keys, args)}
420
+ return self.process_components(
421
+ image_in, modality_selector_left, modality_selector_right, **input_dict
422
+ )
423
+
424
+ def on_selector_change_left(
425
+ self, results_state, image_slider, modality_selector_left
426
+ ):
427
+ results_state = {k: v for v, k in results_state}
428
+ return [results_state[modality_selector_left], image_slider[1]]
429
+
430
+ def on_selector_change_right(
431
+ self, results_state, image_slider, modality_selector_right
432
+ ):
433
+ results_state = {k: v for v, k in results_state}
434
+ return [image_slider[0], results_state[modality_selector_right]]
435
+
436
+ def make_interface(self):
437
+ """
438
+ Constructs the entire Gradio Blocks interface.
439
+ """
440
+ self.make_header()
441
+
442
+ results_state = gr.Gallery(visible=False, format="png")
443
+
444
+ image_slider = self.make_slider()
445
+
446
+ if self.left_selector_visible or not self.advanced_settings_can_be_half_width:
447
+ with gr.Row():
448
+ modality_selector_left, modality_selector_right = (
449
+ self.make_modality_selectors(reverse_visual_order=False)
450
+ )
451
+ user_components, btn_clear, btn_submit = self.make_advanced_settings()
452
+ else:
453
+ with gr.Row(equal_height=False, elem_classes="row_reverse"):
454
+ with gr.Column():
455
+ modality_selector_left, modality_selector_right = (
456
+ self.make_modality_selectors(reverse_visual_order=True)
457
+ )
458
+ with gr.Column():
459
+ user_components, btn_clear, btn_submit = (
460
+ self.make_advanced_settings()
461
+ )
462
+
463
+ self.make_examples(
464
+ image_slider,
465
+ [
466
+ results_state,
467
+ image_slider,
468
+ modality_selector_left,
469
+ modality_selector_right,
470
+ *user_components.values(),
471
+ ],
472
+ )
473
+
474
+ image_slider.upload(
475
+ fn=self.on_process_first,
476
+ inputs=[
477
+ image_slider,
478
+ modality_selector_left,
479
+ modality_selector_right,
480
+ *user_components.values(),
481
+ ],
482
+ outputs=[
483
+ results_state,
484
+ image_slider,
485
+ modality_selector_left,
486
+ modality_selector_right,
487
+ *user_components.values(),
488
+ ],
489
+ )
490
+
491
+ btn_submit.click(
492
+ fn=self.on_process_subsequent,
493
+ inputs=[
494
+ results_state,
495
+ modality_selector_left,
496
+ modality_selector_right,
497
+ *user_components.values(),
498
+ ],
499
+ outputs=[
500
+ results_state,
501
+ image_slider,
502
+ modality_selector_left,
503
+ modality_selector_right,
504
+ *user_components.values(),
505
+ ],
506
+ )
507
+
508
+ btn_clear.click(
509
+ fn=lambda: (None, None),
510
+ inputs=[],
511
+ outputs=[image_slider, results_state],
512
+ )
513
+
514
+ modality_selector_left.input(
515
+ fn=self.on_selector_change_left,
516
+ inputs=[results_state, image_slider, modality_selector_left],
517
+ outputs=image_slider,
518
+ )
519
+ modality_selector_right.input(
520
+ fn=self.on_selector_change_right,
521
+ inputs=[results_state, image_slider, modality_selector_right],
522
+ outputs=image_slider,
523
+ )
524
+
525
+ def make_header(self):
526
+ """
527
+ Create a header section with Markdown and HTML.
528
+ Default: just the project title.
529
+ """
530
+ gr.Markdown(f"# {self.title}")
531
+
532
+ def make_slider(self):
533
+ with gr.Row(elem_classes="sliderrow"):
534
+ return ImageSliderPlus(
535
+ label=self.title,
536
+ type="filepath",
537
+ elem_classes="slider",
538
+ position=self.slider_position,
539
+ )
540
+
541
+ def make_modality_selectors(self, reverse_visual_order=False):
542
+ modality_selector_left = Radio(
543
+ choices=None,
544
+ value=None,
545
+ label="Left",
546
+ key="Left",
547
+ show_label=False,
548
+ container=False,
549
+ visible=self.left_selector_visible,
550
+ render=not reverse_visual_order,
551
+ )
552
+ modality_selector_right = Radio(
553
+ choices=None,
554
+ value=None,
555
+ label="Right",
556
+ key="Right",
557
+ show_label=False,
558
+ container=False,
559
+ elem_id="selector_right",
560
+ render=not reverse_visual_order,
561
+ )
562
+ if reverse_visual_order:
563
+ modality_selector_right.render()
564
+ modality_selector_left.render()
565
+ return modality_selector_left, modality_selector_right
566
+
567
+ def make_examples(self, inputs, outputs):
568
+ examples = self.discover_examples()
569
+ if not isinstance(examples, list):
570
+ raise gr.Error("`discover_examples` must return a list of paths")
571
+ if any(not os.path.isfile(path) for path in examples):
572
+ raise gr.Error("Not all example paths are valid files")
573
+ examples_dirname = os.path.basename(os.path.normpath(self.examples_path))
574
+ return Examples(
575
+ examples=[
576
+ (e, e) for e in examples
577
+ ], # tuples like this seem to work better with the gallery
578
+ inputs=inputs,
579
+ outputs=outputs,
580
+ examples_per_page=self.examples_per_page,
581
+ cache_examples=self.examples_cache,
582
+ fn=self.on_process_first,
583
+ directory_name=examples_dirname,
584
+ )
585
+
586
+ def make_advanced_settings(self):
587
+ with gr.Accordion("Advanced Settings", open=False):
588
+ user_components = self.build_user_components()
589
+ if not isinstance(user_components, dict) or any(
590
+ not isinstance(k, str) or not isinstance(v, Component)
591
+ for k, v in user_components.items()
592
+ ):
593
+ raise gr.Error(
594
+ "`build_user_components` must return a dict of Gradio components with string keys. A dict of the "
595
+ "same structure will be passed into the `process` function."
596
+ )
597
+ with gr.Row():
598
+ btn_clear, btn_submit = self.make_buttons()
599
+ self.input_keys = list(user_components.keys())
600
+ return user_components, btn_clear, btn_submit
601
+
602
+ def make_buttons(self):
603
+ btn_clear = gr.Button("Clear")
604
+ btn_submit = gr.Button("Apply", variant="primary")
605
+ return btn_clear, btn_submit
gradio_dualvision/gradio_patches/__init__.py ADDED
File without changes
gradio_dualvision/gradio_patches/examples.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing. It was developed
6
+ # to support the Marigold project. If you find this code useful, we kindly
7
+ # ask you to cite our most relevant papers.
8
+ # More information about Marigold:
9
+ # https://marigoldmonodepth.github.io
10
+ # https://marigoldcomputervision.github.io
11
+ # Efficient inference pipelines are now part of diffusers:
12
+ # https://huggingface.co/docs/diffusers/using-diffusers/marigold_usage
13
+ # https://huggingface.co/docs/diffusers/api/pipelines/marigold
14
+ # Examples of trained models and live demos:
15
+ # https://huggingface.co/prs-eth
16
+ # Related projects:
17
+ # https://marigolddepthcompletion.github.io/
18
+ # https://rollingdepth.github.io/
19
+ # Citation (BibTeX):
20
+ # https://github.com/prs-eth/Marigold#-citation
21
+ # https://github.com/prs-eth/Marigold-DC#-citation
22
+ # https://github.com/prs-eth/rollingdepth#-citation
23
+ # --------------------------------------------------------------------------
24
+ from pathlib import Path
25
+ import gradio
26
+ from gradio.utils import get_cache_folder
27
+
28
+
29
+ class Examples(gradio.helpers.Examples):
30
+ def __init__(self, *args, directory_name=None, **kwargs):
31
+ super().__init__(*args, **kwargs, _initiated_directly=False)
32
+ if directory_name is not None:
33
+ self.cached_folder = get_cache_folder() / directory_name
34
+ self.cached_file = Path(self.cached_folder) / "log.csv"
35
+ self.cached_indices_file = Path(self.cached_folder) / "indices.csv"
36
+ self.create()
gradio_dualvision/gradio_patches/imagesliderplus.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing. It was developed
6
+ # to support the Marigold project. If you find this code useful, we kindly
7
+ # ask you to cite our most relevant papers.
8
+ # More information about Marigold:
9
+ # https://marigoldmonodepth.github.io
10
+ # https://marigoldcomputervision.github.io
11
+ # Efficient inference pipelines are now part of diffusers:
12
+ # https://huggingface.co/docs/diffusers/using-diffusers/marigold_usage
13
+ # https://huggingface.co/docs/diffusers/api/pipelines/marigold
14
+ # Examples of trained models and live demos:
15
+ # https://huggingface.co/prs-eth
16
+ # Related projects:
17
+ # https://marigolddepthcompletion.github.io/
18
+ # https://rollingdepth.github.io/
19
+ # Citation (BibTeX):
20
+ # https://github.com/prs-eth/Marigold#-citation
21
+ # https://github.com/prs-eth/Marigold-DC#-citation
22
+ # https://github.com/prs-eth/rollingdepth#-citation
23
+ # --------------------------------------------------------------------------
24
+ import json
25
+ import os.path
26
+ import tempfile
27
+ from pathlib import Path
28
+ from typing import Union, Tuple, Optional
29
+
30
+ import numpy as np
31
+ from PIL import Image
32
+ from gradio import processing_utils
33
+ from gradio import utils
34
+ from gradio.data_classes import FileData, GradioRootModel, JsonData
35
+ from gradio_client import utils as client_utils
36
+ from gradio_imageslider import ImageSlider
37
+ from gradio_imageslider.imageslider import image_tuple, image_variants
38
+
39
+
40
+ class ImageSliderPlusData(GradioRootModel):
41
+ root: Union[
42
+ Tuple[FileData | None, FileData | None, JsonData | None],
43
+ Tuple[FileData | None, FileData | None],
44
+ None,
45
+ ]
46
+
47
+
48
+ class ImageSliderPlus(ImageSlider):
49
+ data_model = ImageSliderPlusData
50
+
51
+ def as_example(self, value):
52
+ return self.process_example_dims(value, 256)
53
+
54
+ def _format_image(self, im: Image):
55
+ if self.type != "filepath":
56
+ raise ValueError("ImageSliderPlus can be only created with type='filepath'")
57
+ if im is None:
58
+ return im
59
+ format = "png" if im.mode == "I;16" else "webp"
60
+ path = processing_utils.save_pil_to_cache(
61
+ im, cache_dir=self.GRADIO_CACHE, format=format
62
+ )
63
+ self.temp_files.add(path)
64
+ return path
65
+
66
+ def _postprocess_image(self, y: image_variants):
67
+ if isinstance(y, np.ndarray):
68
+ format = "png" if y.dtype == np.uint16 and y.squeeze().ndim == 2 else "webp"
69
+ path = processing_utils.save_img_array_to_cache(
70
+ y, cache_dir=self.GRADIO_CACHE, format=format
71
+ )
72
+ elif isinstance(y, Image.Image):
73
+ format = "png" if y.mode == "I;16" else "webp"
74
+ path = processing_utils.save_pil_to_cache(
75
+ y, cache_dir=self.GRADIO_CACHE, format=format
76
+ )
77
+ elif isinstance(y, (str, Path)):
78
+ path = y if isinstance(y, str) else str(utils.abspath(y))
79
+ else:
80
+ raise ValueError("Cannot process this value as an Image")
81
+
82
+ return path
83
+
84
+ def postprocess(
85
+ self,
86
+ y: image_tuple,
87
+ ) -> ImageSliderPlusData:
88
+ if y is None:
89
+ return ImageSliderPlusData(root=(None, None, None))
90
+
91
+ settings = None
92
+ if type(y[0]) is str:
93
+ settings_candidate_path = y[0] + ".settings.json"
94
+ if os.path.isfile(settings_candidate_path):
95
+ with open(settings_candidate_path, "r") as fp:
96
+ settings = json.load(fp)
97
+
98
+ return ImageSliderPlusData(
99
+ root=(
100
+ FileData(path=self._postprocess_image(y[0])),
101
+ FileData(path=self._postprocess_image(y[1])),
102
+ JsonData(settings),
103
+ ),
104
+ )
105
+
106
+ def preprocess(self, x: ImageSliderPlusData) -> image_tuple:
107
+ if x is None:
108
+ return x
109
+
110
+ out_0 = self._preprocess_image(x.root[0])
111
+ out_1 = self._preprocess_image(x.root[1])
112
+
113
+ if len(x.root) > 2 and x.root[2] is not None:
114
+ with open(out_0 + ".settings.json", "w") as fp:
115
+ json.dump(x.root[2].root, fp)
116
+
117
+ return out_0, out_1
118
+
119
+ @staticmethod
120
+ def resize_and_save(image_path: str, max_dim: int) -> str:
121
+ img = Image.open(image_path).convert("RGB")
122
+ img.thumbnail((max_dim, max_dim))
123
+ temp_file = tempfile.NamedTemporaryFile(suffix=".webp", delete=False)
124
+ img.save(temp_file.name, "WEBP")
125
+ return temp_file.name
126
+
127
+ def process_example_dims(
128
+ self, input_data: tuple[str | Path | None] | None, max_dim: Optional[int] = None
129
+ ) -> image_tuple:
130
+ if input_data is None:
131
+ return None
132
+ input_data = (str(input_data[0]), str(input_data[1]))
133
+ if self.proxy_url or client_utils.is_http_url_like(input_data[0]):
134
+ return input_data[0]
135
+ if max_dim is not None:
136
+ input_data = (
137
+ self.resize_and_save(input_data[0], max_dim),
138
+ self.resize_and_save(input_data[1], max_dim),
139
+ )
140
+ return (
141
+ self.move_resource_to_block_cache(input_data[0]),
142
+ self.move_resource_to_block_cache(input_data[1]),
143
+ )
144
+
145
+ def process_example(
146
+ self, input_data: tuple[str | Path | None] | None
147
+ ) -> image_tuple:
148
+ return self.process_example_dims(input_data)
gradio_dualvision/gradio_patches/radio.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing. It was developed
6
+ # to support the Marigold project. If you find this code useful, we kindly
7
+ # ask you to cite our most relevant papers.
8
+ # More information about Marigold:
9
+ # https://marigoldmonodepth.github.io
10
+ # https://marigoldcomputervision.github.io
11
+ # Efficient inference pipelines are now part of diffusers:
12
+ # https://huggingface.co/docs/diffusers/using-diffusers/marigold_usage
13
+ # https://huggingface.co/docs/diffusers/api/pipelines/marigold
14
+ # Examples of trained models and live demos:
15
+ # https://huggingface.co/prs-eth
16
+ # Related projects:
17
+ # https://marigolddepthcompletion.github.io/
18
+ # https://rollingdepth.github.io/
19
+ # Citation (BibTeX):
20
+ # https://github.com/prs-eth/Marigold#-citation
21
+ # https://github.com/prs-eth/Marigold-DC#-citation
22
+ # https://github.com/prs-eth/rollingdepth#-citation
23
+ # --------------------------------------------------------------------------
24
+ import gradio
25
+ from gradio import components
26
+ from gradio.components.base import Component
27
+ from gradio.data_classes import (
28
+ GradioModel,
29
+ GradioRootModel,
30
+ )
31
+
32
+ from gradio.blocks import BlockContext
33
+
34
+
35
+ def patched_postprocess_update_dict(
36
+ block: Component | BlockContext, update_dict: dict, postprocess: bool = True
37
+ ):
38
+ """
39
+ This is a patched version of the original function where 'pop' is replaced with 'get' in the first line.
40
+ The key will no longer be removed but can still be accessed safely.
41
+ This fixed gradio.Radio component persisting the value selection through gradio.Examples.
42
+ """
43
+ value = update_dict.get("value", components._Keywords.NO_VALUE)
44
+
45
+ # Continue with the original logic
46
+ update_dict = {k: getattr(block, k) for k in update_dict if hasattr(block, k)}
47
+ if value is not components._Keywords.NO_VALUE:
48
+ if postprocess:
49
+ update_dict["value"] = block.postprocess(value)
50
+ if isinstance(update_dict["value"], (GradioModel, GradioRootModel)):
51
+ update_dict["value"] = update_dict["value"].model_dump()
52
+ else:
53
+ update_dict["value"] = value
54
+ update_dict["__type__"] = "update"
55
+ return update_dict
56
+
57
+
58
+ gradio.blocks.postprocess_update_dict = patched_postprocess_update_dict
59
+
60
+
61
+ class Radio(gradio.Radio):
62
+ pass
gradio_dualvision/gradio_patches/templates/component/__vite-browser-external-2447137e.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ const e = {};
2
+ export {
3
+ e as default
4
+ };
gradio_dualvision/gradio_patches/templates/component/index.js ADDED
The diff for this file is too large to render. See raw diff
 
gradio_dualvision/gradio_patches/templates/component/style.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .wrap.svelte-1w37x6c.svelte-1w37x6c{position:relative;width:100%;height:100%;z-index:100}.icon-wrap.svelte-1w37x6c.svelte-1w37x6c{position:absolute;top:50%;transform:translateY(-50%);left:-40px;width:32px;transition:.2s;color:var(--body-text-color)}.icon-wrap.right.svelte-1w37x6c.svelte-1w37x6c{left:60px;transform:translateY(-50%) translate(-100%) rotate(180deg)}.icon-wrap.active.svelte-1w37x6c.svelte-1w37x6c,.icon-wrap.disabled.svelte-1w37x6c.svelte-1w37x6c{opacity:0}.outer.svelte-1w37x6c.svelte-1w37x6c{width:20px;height:100%;cursor:grab;position:absolute;top:0;left:0}.inner.svelte-1w37x6c.svelte-1w37x6c{box-shadow:-1px 0 6px 1px #0003;width:1px;height:100%;background:var(--color);position:absolute;left:calc((100% - 2px)/2)}.disabled.svelte-1w37x6c.svelte-1w37x6c{cursor:auto}.disabled.svelte-1w37x6c .inner.svelte-1w37x6c{box-shadow:none}.block.svelte-1t38q2d{position:relative;margin:0;box-shadow:var(--block-shadow);border-width:var(--block-border-width);border-color:var(--block-border-color);border-radius:var(--block-radius);background:var(--block-background-fill);width:100%;line-height:var(--line-sm)}.block.border_focus.svelte-1t38q2d{border-color:var(--color-accent)}.padded.svelte-1t38q2d{padding:var(--block-padding)}.hidden.svelte-1t38q2d{display:none}.hide-container.svelte-1t38q2d{margin:0;box-shadow:none;--block-border-width:0;background:transparent;padding:0;overflow:visible}div.svelte-1hnfib2{margin-bottom:var(--spacing-lg);color:var(--block-info-text-color);font-weight:var(--block-info-text-weight);font-size:var(--block-info-text-size);line-height:var(--line-sm)}span.has-info.svelte-22c38v{margin-bottom:var(--spacing-xs)}span.svelte-22c38v:not(.has-info){margin-bottom:var(--spacing-lg)}span.svelte-22c38v{display:inline-block;position:relative;z-index:var(--layer-4);border:solid var(--block-title-border-width) var(--block-title-border-color);border-radius:var(--block-title-radius);background:var(--block-title-background-fill);padding:var(--block-title-padding);color:var(--block-title-text-color);font-weight:var(--block-title-text-weight);font-size:var(--block-title-text-size);line-height:var(--line-sm)}.hide.svelte-22c38v{margin:0;height:0}label.svelte-9gxdi0{display:inline-flex;align-items:center;z-index:var(--layer-2);box-shadow:var(--block-label-shadow);border:var(--block-label-border-width) solid var(--border-color-primary);border-top:none;border-left:none;border-radius:var(--block-label-radius);background:var(--block-label-background-fill);padding:var(--block-label-padding);pointer-events:none;color:var(--block-label-text-color);font-weight:var(--block-label-text-weight);font-size:var(--block-label-text-size);line-height:var(--line-sm)}.gr-group label.svelte-9gxdi0{border-top-left-radius:0}label.float.svelte-9gxdi0{position:absolute;top:var(--block-label-margin);left:var(--block-label-margin)}label.svelte-9gxdi0:not(.float){position:static;margin-top:var(--block-label-margin);margin-left:var(--block-label-margin)}.hide.svelte-9gxdi0{height:0}span.svelte-9gxdi0{opacity:.8;margin-right:var(--size-2);width:calc(var(--block-label-text-size) - 1px);height:calc(var(--block-label-text-size) - 1px)}.hide-label.svelte-9gxdi0{box-shadow:none;border-width:0;background:transparent;overflow:visible}button.svelte-lpi64a{display:flex;justify-content:center;align-items:center;gap:1px;z-index:var(--layer-2);border-radius:var(--radius-sm);color:var(--block-label-text-color);border:1px solid transparent}button[disabled].svelte-lpi64a{opacity:.5;box-shadow:none}button[disabled].svelte-lpi64a:hover{cursor:not-allowed}.padded.svelte-lpi64a{padding:2px;background:var(--bg-color);box-shadow:var(--shadow-drop);border:1px solid var(--button-secondary-border-color)}button.svelte-lpi64a:hover,button.highlight.svelte-lpi64a{cursor:pointer;color:var(--color-accent)}.padded.svelte-lpi64a:hover{border:2px solid var(--button-secondary-border-color-hover);padding:1px;color:var(--block-label-text-color)}span.svelte-lpi64a{padding:0 1px;font-size:10px}div.svelte-lpi64a{padding:2px;display:flex;align-items:flex-end}.small.svelte-lpi64a{width:14px;height:14px}.large.svelte-lpi64a{width:22px;height:22px}.pending.svelte-lpi64a{animation:svelte-lpi64a-flash .5s infinite}@keyframes svelte-lpi64a-flash{0%{opacity:.5}50%{opacity:1}to{opacity:.5}}.transparent.svelte-lpi64a{background:transparent;border:none;box-shadow:none}.empty.svelte-3w3rth{display:flex;justify-content:center;align-items:center;margin-top:calc(0px - var(--size-6));height:var(--size-full)}.icon.svelte-3w3rth{opacity:.5;height:var(--size-5);color:var(--body-text-color)}.small.svelte-3w3rth{min-height:calc(var(--size-32) - 20px)}.large.svelte-3w3rth{min-height:calc(var(--size-64) - 20px)}.unpadded_box.svelte-3w3rth{margin-top:0}.small_parent.svelte-3w3rth{min-height:100%!important}.dropdown-arrow.svelte-145leq6{fill:currentColor}.wrap.svelte-kzcjhc{display:flex;flex-direction:column;justify-content:center;align-items:center;min-height:var(--size-60);color:var(--block-label-text-color);line-height:var(--line-md);height:100%;padding-top:var(--size-3)}.or.svelte-kzcjhc{color:var(--body-text-color-subdued);display:flex}.icon-wrap.svelte-kzcjhc{width:30px;margin-bottom:var(--spacing-lg)}@media (--screen-md){.wrap.svelte-kzcjhc{font-size:var(--text-lg)}}.hovered.svelte-kzcjhc{color:var(--color-accent)}div.svelte-ipfyu7{border-top:1px solid transparent;display:flex;max-height:100%;justify-content:center;gap:var(--spacing-sm);height:auto;align-items:flex-end;padding-bottom:var(--spacing-xl);color:var(--block-label-text-color);flex-shrink:0;width:95%}.show_border.svelte-ipfyu7{border-top:1px solid var(--block-border-color);margin-top:var(--spacing-xxl);box-shadow:var(--shadow-drop)}.source-selection.svelte-lde7lt{display:flex;align-items:center;justify-content:center;border-top:1px solid var(--border-color-primary);width:95%;bottom:0;left:0;right:0;margin-left:auto;margin-right:auto;align-self:flex-end}.icon.svelte-lde7lt{width:22px;height:22px;margin:var(--spacing-lg) var(--spacing-xs);padding:var(--spacing-xs);color:var(--neutral-400);border-radius:var(--radius-md)}.selected.svelte-lde7lt{color:var(--color-accent)}.icon.svelte-lde7lt:hover,.icon.svelte-lde7lt:focus{color:var(--color-accent)}div.svelte-1g74h68{display:flex;position:absolute;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-5)}.wrap.svelte-1juivz4.svelte-1juivz4{overflow-y:auto;transition:opacity .5s ease-in-out;background:var(--block-background-fill);position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:var(--size-40);width:100%}.wrap.svelte-1juivz4.svelte-1juivz4:after{content:"";position:absolute;top:0;left:0;width:var(--upload-progress-width);height:100%;transition:all .5s ease-in-out;z-index:1}.uploading.svelte-1juivz4.svelte-1juivz4{font-size:var(--text-lg);font-family:var(--font);z-index:2}.file-name.svelte-1juivz4.svelte-1juivz4{margin:var(--spacing-md);font-size:var(--text-lg);color:var(--body-text-color-subdued)}.file.svelte-1juivz4.svelte-1juivz4{font-size:var(--text-md);z-index:2;display:flex;align-items:center}.file.svelte-1juivz4 progress.svelte-1juivz4{display:inline;height:var(--size-1);width:100%;transition:all .5s ease-in-out;color:var(--color-accent);border:none}.file.svelte-1juivz4 progress[value].svelte-1juivz4::-webkit-progress-value{background-color:var(--color-accent);border-radius:20px}.file.svelte-1juivz4 progress[value].svelte-1juivz4::-webkit-progress-bar{background-color:var(--border-color-accent);border-radius:20px}.progress-bar.svelte-1juivz4.svelte-1juivz4{width:14px;height:14px;border-radius:50%;background:radial-gradient(closest-side,var(--block-background-fill) 64%,transparent 53% 100%),conic-gradient(var(--color-accent) var(--upload-progress-width),var(--border-color-accent) 0);transition:all .5s ease-in-out}button.svelte-1aq8tno{cursor:pointer;width:var(--size-full)}.hidden.svelte-1aq8tno{display:none;height:0!important;position:absolute;width:0;flex-grow:0}.center.svelte-1aq8tno{display:flex;justify-content:center}.flex.svelte-1aq8tno{display:flex;justify-content:center;align-items:center}input.svelte-1aq8tno{display:none}div.svelte-1wj0ocy{display:flex;top:var(--size-2);right:var(--size-2);justify-content:flex-end;gap:var(--spacing-sm);z-index:var(--layer-1)}.not-absolute.svelte-1wj0ocy{margin:var(--size-1)}.upload-wrap.svelte-106mu0e.svelte-106mu0e{display:flex;justify-content:center;align-items:center;height:100%;width:100%}.wrap.svelte-106mu0e.svelte-106mu0e{width:100%}.half-wrap.svelte-106mu0e.svelte-106mu0e{width:50%}.image-container.svelte-106mu0e.svelte-106mu0e,img.svelte-106mu0e.svelte-106mu0e,.empty-wrap.svelte-106mu0e.svelte-106mu0e{width:var(--size-full);height:var(--size-full)}img.svelte-106mu0e.svelte-106mu0e{object-fit:cover}.fixed.svelte-106mu0e.svelte-106mu0e{--anim-block-background-fill:255, 255, 255;position:absolute;top:0;left:0;background-color:rgba(var(--anim-block-background-fill),.8);z-index:0}@media (prefers-color-scheme: dark){.fixed.svelte-106mu0e.svelte-106mu0e{--anim-block-background-fill:31, 41, 55}}.side-by-side.svelte-106mu0e img.svelte-106mu0e{width:50%;object-fit:contain}.empty-wrap.svelte-106mu0e.svelte-106mu0e{pointer-events:none}.icon-buttons.svelte-106mu0e.svelte-106mu0e{display:flex;position:absolute;right:8px;z-index:var(--layer-top);top:8px}svg.svelte-43sxxs.svelte-43sxxs{width:var(--size-20);height:var(--size-20)}svg.svelte-43sxxs path.svelte-43sxxs{fill:var(--loader-color)}div.svelte-43sxxs.svelte-43sxxs{z-index:var(--layer-2)}.margin.svelte-43sxxs.svelte-43sxxs{margin:var(--size-4)}.wrap.svelte-1txqlrd.svelte-1txqlrd{display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:var(--layer-top);transition:opacity .1s ease-in-out;border-radius:var(--block-radius);background:var(--block-background-fill);padding:0 var(--size-6);max-height:var(--size-screen-h);overflow:hidden;pointer-events:none}.wrap.center.svelte-1txqlrd.svelte-1txqlrd{top:0;right:0;left:0}.wrap.default.svelte-1txqlrd.svelte-1txqlrd{top:0;right:0;bottom:0;left:0}.hide.svelte-1txqlrd.svelte-1txqlrd{opacity:0;pointer-events:none}.generating.svelte-1txqlrd.svelte-1txqlrd{animation:svelte-1txqlrd-pulse 2s cubic-bezier(.4,0,.6,1) infinite;border:2px solid var(--color-accent);background:transparent}.translucent.svelte-1txqlrd.svelte-1txqlrd{background:none}@keyframes svelte-1txqlrd-pulse{0%,to{opacity:1}50%{opacity:.5}}.loading.svelte-1txqlrd.svelte-1txqlrd{z-index:var(--layer-2);color:var(--body-text-color)}.eta-bar.svelte-1txqlrd.svelte-1txqlrd{position:absolute;top:0;right:0;bottom:0;left:0;transform-origin:left;opacity:.8;z-index:var(--layer-1);transition:10ms;background:var(--background-fill-secondary)}.progress-bar-wrap.svelte-1txqlrd.svelte-1txqlrd{border:1px solid var(--border-color-primary);background:var(--background-fill-primary);width:55.5%;height:var(--size-4)}.progress-bar.svelte-1txqlrd.svelte-1txqlrd{transform-origin:left;background-color:var(--loader-color);width:var(--size-full);height:var(--size-full)}.progress-level.svelte-1txqlrd.svelte-1txqlrd{display:flex;flex-direction:column;align-items:center;gap:1;z-index:var(--layer-2);width:var(--size-full)}.progress-level-inner.svelte-1txqlrd.svelte-1txqlrd{margin:var(--size-2) auto;color:var(--body-text-color);font-size:var(--text-sm);font-family:var(--font-mono)}.meta-text.svelte-1txqlrd.svelte-1txqlrd{position:absolute;top:0;right:0;z-index:var(--layer-2);padding:var(--size-1) var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono)}.meta-text-center.svelte-1txqlrd.svelte-1txqlrd{display:flex;position:absolute;top:0;right:0;justify-content:center;align-items:center;transform:translateY(var(--size-6));z-index:var(--layer-2);padding:var(--size-1) var(--size-2);font-size:var(--text-sm);font-family:var(--font-mono);text-align:center}.error.svelte-1txqlrd.svelte-1txqlrd{box-shadow:var(--shadow-drop);border:solid 1px var(--error-border-color);border-radius:var(--radius-full);background:var(--error-background-fill);padding-right:var(--size-4);padding-left:var(--size-4);color:var(--error-text-color);font-weight:var(--weight-semibold);font-size:var(--text-lg);line-height:var(--line-lg);font-family:var(--font)}.minimal.svelte-1txqlrd .progress-text.svelte-1txqlrd{background:var(--block-background-fill)}.border.svelte-1txqlrd.svelte-1txqlrd{border:1px solid var(--border-color-primary)}.toast-body.svelte-solcu7{display:flex;position:relative;right:0;left:0;align-items:center;margin:var(--size-6) var(--size-4);margin:auto;border-radius:var(--container-radius);overflow:hidden;pointer-events:auto}.toast-body.error.svelte-solcu7{border:1px solid var(--color-red-700);background:var(--color-red-50)}.dark .toast-body.error.svelte-solcu7{border:1px solid var(--color-red-500);background-color:var(--color-grey-950)}.toast-body.warning.svelte-solcu7{border:1px solid var(--color-yellow-700);background:var(--color-yellow-50)}.dark .toast-body.warning.svelte-solcu7{border:1px solid var(--color-yellow-500);background-color:var(--color-grey-950)}.toast-body.info.svelte-solcu7{border:1px solid var(--color-grey-700);background:var(--color-grey-50)}.dark .toast-body.info.svelte-solcu7{border:1px solid var(--color-grey-500);background-color:var(--color-grey-950)}.toast-title.svelte-solcu7{display:flex;align-items:center;font-weight:var(--weight-bold);font-size:var(--text-lg);line-height:var(--line-sm);text-transform:capitalize}.toast-title.error.svelte-solcu7{color:var(--color-red-700)}.dark .toast-title.error.svelte-solcu7{color:var(--color-red-50)}.toast-title.warning.svelte-solcu7{color:var(--color-yellow-700)}.dark .toast-title.warning.svelte-solcu7{color:var(--color-yellow-50)}.toast-title.info.svelte-solcu7{color:var(--color-grey-700)}.dark .toast-title.info.svelte-solcu7{color:var(--color-grey-50)}.toast-close.svelte-solcu7{margin:0 var(--size-3);border-radius:var(--size-3);padding:0px var(--size-1-5);font-size:var(--size-5);line-height:var(--size-5)}.toast-close.error.svelte-solcu7{color:var(--color-red-700)}.dark .toast-close.error.svelte-solcu7{color:var(--color-red-500)}.toast-close.warning.svelte-solcu7{color:var(--color-yellow-700)}.dark .toast-close.warning.svelte-solcu7{color:var(--color-yellow-500)}.toast-close.info.svelte-solcu7{color:var(--color-grey-700)}.dark .toast-close.info.svelte-solcu7{color:var(--color-grey-500)}.toast-text.svelte-solcu7{font-size:var(--text-lg)}.toast-text.error.svelte-solcu7{color:var(--color-red-700)}.dark .toast-text.error.svelte-solcu7{color:var(--color-red-50)}.toast-text.warning.svelte-solcu7{color:var(--color-yellow-700)}.dark .toast-text.warning.svelte-solcu7{color:var(--color-yellow-50)}.toast-text.info.svelte-solcu7{color:var(--color-grey-700)}.dark .toast-text.info.svelte-solcu7{color:var(--color-grey-50)}.toast-details.svelte-solcu7{margin:var(--size-3) var(--size-3) var(--size-3) 0;width:100%}.toast-icon.svelte-solcu7{display:flex;position:absolute;position:relative;flex-shrink:0;justify-content:center;align-items:center;margin:var(--size-2);border-radius:var(--radius-full);padding:var(--size-1);padding-left:calc(var(--size-1) - 1px);width:35px;height:35px}.toast-icon.error.svelte-solcu7{color:var(--color-red-700)}.dark .toast-icon.error.svelte-solcu7{color:var(--color-red-500)}.toast-icon.warning.svelte-solcu7{color:var(--color-yellow-700)}.dark .toast-icon.warning.svelte-solcu7{color:var(--color-yellow-500)}.toast-icon.info.svelte-solcu7{color:var(--color-grey-700)}.dark .toast-icon.info.svelte-solcu7{color:var(--color-grey-500)}@keyframes svelte-solcu7-countdown{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.timer.svelte-solcu7{position:absolute;bottom:0;left:0;transform-origin:0 0;animation:svelte-solcu7-countdown 10s linear forwards;width:100%;height:var(--size-1)}.timer.error.svelte-solcu7{background:var(--color-red-700)}.dark .timer.error.svelte-solcu7{background:var(--color-red-500)}.timer.warning.svelte-solcu7{background:var(--color-yellow-700)}.dark .timer.warning.svelte-solcu7{background:var(--color-yellow-500)}.timer.info.svelte-solcu7{background:var(--color-grey-700)}.dark .timer.info.svelte-solcu7{background:var(--color-grey-500)}.toast-wrap.svelte-gatr8h{display:flex;position:fixed;top:var(--size-4);right:var(--size-4);flex-direction:column;align-items:end;gap:var(--size-2);z-index:var(--layer-top);width:calc(100% - var(--size-8))}@media (--screen-sm){.toast-wrap.svelte-gatr8h{width:calc(var(--size-96) + var(--size-10))}}.slider-wrap.svelte-a2zf8o{-webkit-user-select:none;user-select:none;max-height:calc(100vh - 40px)}img.svelte-a2zf8o{width:var(--size-full);height:var(--size-full);object-fit:cover}.fixed.svelte-a2zf8o{position:absolute;top:0;left:0}.hidden.svelte-a2zf8o{opacity:0}.icon-buttons.svelte-a2zf8o{display:flex;position:absolute;right:8px;z-index:var(--layer-top);top:8px}.status-wrap.svelte-6wvohu{position:absolute;height:100%;width:100%;--anim-block-background-fill:255, 255, 255;z-index:1;pointer-events:none}@media (prefers-color-scheme: dark){.status-wrap.svelte-6wvohu{--anim-block-background-fill:31, 41, 55}}@keyframes svelte-6wvohu-pulse{0%{background-color:rgba(var(--anim-block-background-fill),.7)}50%{background-color:rgba(var(--anim-block-background-fill),.4)}to{background-color:rgba(var(--anim-block-background-fill),.7)}}.status-wrap.half.svelte-6wvohu .wrap{border-radius:0;animation:svelte-6wvohu-pulse 1.4s infinite ease-in-out}.status-wrap.half.svelte-6wvohu .progress-text{background:none!important}.status-wrap.half.svelte-6wvohu .eta-bar{opacity:0}.icon-buttons.svelte-6wvohu{display:flex;position:absolute;right:6px;z-index:var(--layer-1);top:6px}
gradio_dualvision/gradio_patches/templates/component/wrapper-6f348d45-19fa94bf.js ADDED
@@ -0,0 +1,2453 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import S from "./__vite-browser-external-2447137e.js";
2
+ function z(s) {
3
+ return s && s.__esModule && Object.prototype.hasOwnProperty.call(s, "default") ? s.default : s;
4
+ }
5
+ function gt(s) {
6
+ if (s.__esModule)
7
+ return s;
8
+ var e = s.default;
9
+ if (typeof e == "function") {
10
+ var t = function r() {
11
+ if (this instanceof r) {
12
+ var i = [null];
13
+ i.push.apply(i, arguments);
14
+ var n = Function.bind.apply(e, i);
15
+ return new n();
16
+ }
17
+ return e.apply(this, arguments);
18
+ };
19
+ t.prototype = e.prototype;
20
+ } else
21
+ t = {};
22
+ return Object.defineProperty(t, "__esModule", { value: !0 }), Object.keys(s).forEach(function(r) {
23
+ var i = Object.getOwnPropertyDescriptor(s, r);
24
+ Object.defineProperty(t, r, i.get ? i : {
25
+ enumerable: !0,
26
+ get: function() {
27
+ return s[r];
28
+ }
29
+ });
30
+ }), t;
31
+ }
32
+ const { Duplex: yt } = S;
33
+ function Oe(s) {
34
+ s.emit("close");
35
+ }
36
+ function vt() {
37
+ !this.destroyed && this._writableState.finished && this.destroy();
38
+ }
39
+ function Qe(s) {
40
+ this.removeListener("error", Qe), this.destroy(), this.listenerCount("error") === 0 && this.emit("error", s);
41
+ }
42
+ function St(s, e) {
43
+ let t = !0;
44
+ const r = new yt({
45
+ ...e,
46
+ autoDestroy: !1,
47
+ emitClose: !1,
48
+ objectMode: !1,
49
+ writableObjectMode: !1
50
+ });
51
+ return s.on("message", function(n, o) {
52
+ const l = !o && r._readableState.objectMode ? n.toString() : n;
53
+ r.push(l) || s.pause();
54
+ }), s.once("error", function(n) {
55
+ r.destroyed || (t = !1, r.destroy(n));
56
+ }), s.once("close", function() {
57
+ r.destroyed || r.push(null);
58
+ }), r._destroy = function(i, n) {
59
+ if (s.readyState === s.CLOSED) {
60
+ n(i), process.nextTick(Oe, r);
61
+ return;
62
+ }
63
+ let o = !1;
64
+ s.once("error", function(f) {
65
+ o = !0, n(f);
66
+ }), s.once("close", function() {
67
+ o || n(i), process.nextTick(Oe, r);
68
+ }), t && s.terminate();
69
+ }, r._final = function(i) {
70
+ if (s.readyState === s.CONNECTING) {
71
+ s.once("open", function() {
72
+ r._final(i);
73
+ });
74
+ return;
75
+ }
76
+ s._socket !== null && (s._socket._writableState.finished ? (i(), r._readableState.endEmitted && r.destroy()) : (s._socket.once("finish", function() {
77
+ i();
78
+ }), s.close()));
79
+ }, r._read = function() {
80
+ s.isPaused && s.resume();
81
+ }, r._write = function(i, n, o) {
82
+ if (s.readyState === s.CONNECTING) {
83
+ s.once("open", function() {
84
+ r._write(i, n, o);
85
+ });
86
+ return;
87
+ }
88
+ s.send(i, o);
89
+ }, r.on("end", vt), r.on("error", Qe), r;
90
+ }
91
+ var Et = St;
92
+ const Vs = /* @__PURE__ */ z(Et);
93
+ var te = { exports: {} }, U = {
94
+ BINARY_TYPES: ["nodebuffer", "arraybuffer", "fragments"],
95
+ EMPTY_BUFFER: Buffer.alloc(0),
96
+ GUID: "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
97
+ kForOnEventAttribute: Symbol("kIsForOnEventAttribute"),
98
+ kListener: Symbol("kListener"),
99
+ kStatusCode: Symbol("status-code"),
100
+ kWebSocket: Symbol("websocket"),
101
+ NOOP: () => {
102
+ }
103
+ }, bt, xt;
104
+ const { EMPTY_BUFFER: kt } = U, Se = Buffer[Symbol.species];
105
+ function wt(s, e) {
106
+ if (s.length === 0)
107
+ return kt;
108
+ if (s.length === 1)
109
+ return s[0];
110
+ const t = Buffer.allocUnsafe(e);
111
+ let r = 0;
112
+ for (let i = 0; i < s.length; i++) {
113
+ const n = s[i];
114
+ t.set(n, r), r += n.length;
115
+ }
116
+ return r < e ? new Se(t.buffer, t.byteOffset, r) : t;
117
+ }
118
+ function Je(s, e, t, r, i) {
119
+ for (let n = 0; n < i; n++)
120
+ t[r + n] = s[n] ^ e[n & 3];
121
+ }
122
+ function et(s, e) {
123
+ for (let t = 0; t < s.length; t++)
124
+ s[t] ^= e[t & 3];
125
+ }
126
+ function Ot(s) {
127
+ return s.length === s.buffer.byteLength ? s.buffer : s.buffer.slice(s.byteOffset, s.byteOffset + s.length);
128
+ }
129
+ function Ee(s) {
130
+ if (Ee.readOnly = !0, Buffer.isBuffer(s))
131
+ return s;
132
+ let e;
133
+ return s instanceof ArrayBuffer ? e = new Se(s) : ArrayBuffer.isView(s) ? e = new Se(s.buffer, s.byteOffset, s.byteLength) : (e = Buffer.from(s), Ee.readOnly = !1), e;
134
+ }
135
+ te.exports = {
136
+ concat: wt,
137
+ mask: Je,
138
+ toArrayBuffer: Ot,
139
+ toBuffer: Ee,
140
+ unmask: et
141
+ };
142
+ if (!process.env.WS_NO_BUFFER_UTIL)
143
+ try {
144
+ const s = require("bufferutil");
145
+ xt = te.exports.mask = function(e, t, r, i, n) {
146
+ n < 48 ? Je(e, t, r, i, n) : s.mask(e, t, r, i, n);
147
+ }, bt = te.exports.unmask = function(e, t) {
148
+ e.length < 32 ? et(e, t) : s.unmask(e, t);
149
+ };
150
+ } catch {
151
+ }
152
+ var ne = te.exports;
153
+ const Ce = Symbol("kDone"), ue = Symbol("kRun");
154
+ let Ct = class {
155
+ /**
156
+ * Creates a new `Limiter`.
157
+ *
158
+ * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
159
+ * to run concurrently
160
+ */
161
+ constructor(e) {
162
+ this[Ce] = () => {
163
+ this.pending--, this[ue]();
164
+ }, this.concurrency = e || 1 / 0, this.jobs = [], this.pending = 0;
165
+ }
166
+ /**
167
+ * Adds a job to the queue.
168
+ *
169
+ * @param {Function} job The job to run
170
+ * @public
171
+ */
172
+ add(e) {
173
+ this.jobs.push(e), this[ue]();
174
+ }
175
+ /**
176
+ * Removes a job from the queue and runs it if possible.
177
+ *
178
+ * @private
179
+ */
180
+ [ue]() {
181
+ if (this.pending !== this.concurrency && this.jobs.length) {
182
+ const e = this.jobs.shift();
183
+ this.pending++, e(this[Ce]);
184
+ }
185
+ }
186
+ };
187
+ var Tt = Ct;
188
+ const W = S, Te = ne, Lt = Tt, { kStatusCode: tt } = U, Nt = Buffer[Symbol.species], Pt = Buffer.from([0, 0, 255, 255]), se = Symbol("permessage-deflate"), w = Symbol("total-length"), V = Symbol("callback"), C = Symbol("buffers"), J = Symbol("error");
189
+ let K, Rt = class {
190
+ /**
191
+ * Creates a PerMessageDeflate instance.
192
+ *
193
+ * @param {Object} [options] Configuration options
194
+ * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
195
+ * for, or request, a custom client window size
196
+ * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
197
+ * acknowledge disabling of client context takeover
198
+ * @param {Number} [options.concurrencyLimit=10] The number of concurrent
199
+ * calls to zlib
200
+ * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
201
+ * use of a custom server window size
202
+ * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
203
+ * disabling of server context takeover
204
+ * @param {Number} [options.threshold=1024] Size (in bytes) below which
205
+ * messages should not be compressed if context takeover is disabled
206
+ * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
207
+ * deflate
208
+ * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
209
+ * inflate
210
+ * @param {Boolean} [isServer=false] Create the instance in either server or
211
+ * client mode
212
+ * @param {Number} [maxPayload=0] The maximum allowed message length
213
+ */
214
+ constructor(e, t, r) {
215
+ if (this._maxPayload = r | 0, this._options = e || {}, this._threshold = this._options.threshold !== void 0 ? this._options.threshold : 1024, this._isServer = !!t, this._deflate = null, this._inflate = null, this.params = null, !K) {
216
+ const i = this._options.concurrencyLimit !== void 0 ? this._options.concurrencyLimit : 10;
217
+ K = new Lt(i);
218
+ }
219
+ }
220
+ /**
221
+ * @type {String}
222
+ */
223
+ static get extensionName() {
224
+ return "permessage-deflate";
225
+ }
226
+ /**
227
+ * Create an extension negotiation offer.
228
+ *
229
+ * @return {Object} Extension parameters
230
+ * @public
231
+ */
232
+ offer() {
233
+ const e = {};
234
+ return this._options.serverNoContextTakeover && (e.server_no_context_takeover = !0), this._options.clientNoContextTakeover && (e.client_no_context_takeover = !0), this._options.serverMaxWindowBits && (e.server_max_window_bits = this._options.serverMaxWindowBits), this._options.clientMaxWindowBits ? e.client_max_window_bits = this._options.clientMaxWindowBits : this._options.clientMaxWindowBits == null && (e.client_max_window_bits = !0), e;
235
+ }
236
+ /**
237
+ * Accept an extension negotiation offer/response.
238
+ *
239
+ * @param {Array} configurations The extension negotiation offers/reponse
240
+ * @return {Object} Accepted configuration
241
+ * @public
242
+ */
243
+ accept(e) {
244
+ return e = this.normalizeParams(e), this.params = this._isServer ? this.acceptAsServer(e) : this.acceptAsClient(e), this.params;
245
+ }
246
+ /**
247
+ * Releases all resources used by the extension.
248
+ *
249
+ * @public
250
+ */
251
+ cleanup() {
252
+ if (this._inflate && (this._inflate.close(), this._inflate = null), this._deflate) {
253
+ const e = this._deflate[V];
254
+ this._deflate.close(), this._deflate = null, e && e(
255
+ new Error(
256
+ "The deflate stream was closed while data was being processed"
257
+ )
258
+ );
259
+ }
260
+ }
261
+ /**
262
+ * Accept an extension negotiation offer.
263
+ *
264
+ * @param {Array} offers The extension negotiation offers
265
+ * @return {Object} Accepted configuration
266
+ * @private
267
+ */
268
+ acceptAsServer(e) {
269
+ const t = this._options, r = e.find((i) => !(t.serverNoContextTakeover === !1 && i.server_no_context_takeover || i.server_max_window_bits && (t.serverMaxWindowBits === !1 || typeof t.serverMaxWindowBits == "number" && t.serverMaxWindowBits > i.server_max_window_bits) || typeof t.clientMaxWindowBits == "number" && !i.client_max_window_bits));
270
+ if (!r)
271
+ throw new Error("None of the extension offers can be accepted");
272
+ return t.serverNoContextTakeover && (r.server_no_context_takeover = !0), t.clientNoContextTakeover && (r.client_no_context_takeover = !0), typeof t.serverMaxWindowBits == "number" && (r.server_max_window_bits = t.serverMaxWindowBits), typeof t.clientMaxWindowBits == "number" ? r.client_max_window_bits = t.clientMaxWindowBits : (r.client_max_window_bits === !0 || t.clientMaxWindowBits === !1) && delete r.client_max_window_bits, r;
273
+ }
274
+ /**
275
+ * Accept the extension negotiation response.
276
+ *
277
+ * @param {Array} response The extension negotiation response
278
+ * @return {Object} Accepted configuration
279
+ * @private
280
+ */
281
+ acceptAsClient(e) {
282
+ const t = e[0];
283
+ if (this._options.clientNoContextTakeover === !1 && t.client_no_context_takeover)
284
+ throw new Error('Unexpected parameter "client_no_context_takeover"');
285
+ if (!t.client_max_window_bits)
286
+ typeof this._options.clientMaxWindowBits == "number" && (t.client_max_window_bits = this._options.clientMaxWindowBits);
287
+ else if (this._options.clientMaxWindowBits === !1 || typeof this._options.clientMaxWindowBits == "number" && t.client_max_window_bits > this._options.clientMaxWindowBits)
288
+ throw new Error(
289
+ 'Unexpected or invalid parameter "client_max_window_bits"'
290
+ );
291
+ return t;
292
+ }
293
+ /**
294
+ * Normalize parameters.
295
+ *
296
+ * @param {Array} configurations The extension negotiation offers/reponse
297
+ * @return {Array} The offers/response with normalized parameters
298
+ * @private
299
+ */
300
+ normalizeParams(e) {
301
+ return e.forEach((t) => {
302
+ Object.keys(t).forEach((r) => {
303
+ let i = t[r];
304
+ if (i.length > 1)
305
+ throw new Error(`Parameter "${r}" must have only a single value`);
306
+ if (i = i[0], r === "client_max_window_bits") {
307
+ if (i !== !0) {
308
+ const n = +i;
309
+ if (!Number.isInteger(n) || n < 8 || n > 15)
310
+ throw new TypeError(
311
+ `Invalid value for parameter "${r}": ${i}`
312
+ );
313
+ i = n;
314
+ } else if (!this._isServer)
315
+ throw new TypeError(
316
+ `Invalid value for parameter "${r}": ${i}`
317
+ );
318
+ } else if (r === "server_max_window_bits") {
319
+ const n = +i;
320
+ if (!Number.isInteger(n) || n < 8 || n > 15)
321
+ throw new TypeError(
322
+ `Invalid value for parameter "${r}": ${i}`
323
+ );
324
+ i = n;
325
+ } else if (r === "client_no_context_takeover" || r === "server_no_context_takeover") {
326
+ if (i !== !0)
327
+ throw new TypeError(
328
+ `Invalid value for parameter "${r}": ${i}`
329
+ );
330
+ } else
331
+ throw new Error(`Unknown parameter "${r}"`);
332
+ t[r] = i;
333
+ });
334
+ }), e;
335
+ }
336
+ /**
337
+ * Decompress data. Concurrency limited.
338
+ *
339
+ * @param {Buffer} data Compressed data
340
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
341
+ * @param {Function} callback Callback
342
+ * @public
343
+ */
344
+ decompress(e, t, r) {
345
+ K.add((i) => {
346
+ this._decompress(e, t, (n, o) => {
347
+ i(), r(n, o);
348
+ });
349
+ });
350
+ }
351
+ /**
352
+ * Compress data. Concurrency limited.
353
+ *
354
+ * @param {(Buffer|String)} data Data to compress
355
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
356
+ * @param {Function} callback Callback
357
+ * @public
358
+ */
359
+ compress(e, t, r) {
360
+ K.add((i) => {
361
+ this._compress(e, t, (n, o) => {
362
+ i(), r(n, o);
363
+ });
364
+ });
365
+ }
366
+ /**
367
+ * Decompress data.
368
+ *
369
+ * @param {Buffer} data Compressed data
370
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
371
+ * @param {Function} callback Callback
372
+ * @private
373
+ */
374
+ _decompress(e, t, r) {
375
+ const i = this._isServer ? "client" : "server";
376
+ if (!this._inflate) {
377
+ const n = `${i}_max_window_bits`, o = typeof this.params[n] != "number" ? W.Z_DEFAULT_WINDOWBITS : this.params[n];
378
+ this._inflate = W.createInflateRaw({
379
+ ...this._options.zlibInflateOptions,
380
+ windowBits: o
381
+ }), this._inflate[se] = this, this._inflate[w] = 0, this._inflate[C] = [], this._inflate.on("error", Bt), this._inflate.on("data", st);
382
+ }
383
+ this._inflate[V] = r, this._inflate.write(e), t && this._inflate.write(Pt), this._inflate.flush(() => {
384
+ const n = this._inflate[J];
385
+ if (n) {
386
+ this._inflate.close(), this._inflate = null, r(n);
387
+ return;
388
+ }
389
+ const o = Te.concat(
390
+ this._inflate[C],
391
+ this._inflate[w]
392
+ );
393
+ this._inflate._readableState.endEmitted ? (this._inflate.close(), this._inflate = null) : (this._inflate[w] = 0, this._inflate[C] = [], t && this.params[`${i}_no_context_takeover`] && this._inflate.reset()), r(null, o);
394
+ });
395
+ }
396
+ /**
397
+ * Compress data.
398
+ *
399
+ * @param {(Buffer|String)} data Data to compress
400
+ * @param {Boolean} fin Specifies whether or not this is the last fragment
401
+ * @param {Function} callback Callback
402
+ * @private
403
+ */
404
+ _compress(e, t, r) {
405
+ const i = this._isServer ? "server" : "client";
406
+ if (!this._deflate) {
407
+ const n = `${i}_max_window_bits`, o = typeof this.params[n] != "number" ? W.Z_DEFAULT_WINDOWBITS : this.params[n];
408
+ this._deflate = W.createDeflateRaw({
409
+ ...this._options.zlibDeflateOptions,
410
+ windowBits: o
411
+ }), this._deflate[w] = 0, this._deflate[C] = [], this._deflate.on("data", Ut);
412
+ }
413
+ this._deflate[V] = r, this._deflate.write(e), this._deflate.flush(W.Z_SYNC_FLUSH, () => {
414
+ if (!this._deflate)
415
+ return;
416
+ let n = Te.concat(
417
+ this._deflate[C],
418
+ this._deflate[w]
419
+ );
420
+ t && (n = new Nt(n.buffer, n.byteOffset, n.length - 4)), this._deflate[V] = null, this._deflate[w] = 0, this._deflate[C] = [], t && this.params[`${i}_no_context_takeover`] && this._deflate.reset(), r(null, n);
421
+ });
422
+ }
423
+ };
424
+ var oe = Rt;
425
+ function Ut(s) {
426
+ this[C].push(s), this[w] += s.length;
427
+ }
428
+ function st(s) {
429
+ if (this[w] += s.length, this[se]._maxPayload < 1 || this[w] <= this[se]._maxPayload) {
430
+ this[C].push(s);
431
+ return;
432
+ }
433
+ this[J] = new RangeError("Max payload size exceeded"), this[J].code = "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH", this[J][tt] = 1009, this.removeListener("data", st), this.reset();
434
+ }
435
+ function Bt(s) {
436
+ this[se]._inflate = null, s[tt] = 1007, this[V](s);
437
+ }
438
+ var re = { exports: {} };
439
+ const $t = {}, Mt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
440
+ __proto__: null,
441
+ default: $t
442
+ }, Symbol.toStringTag, { value: "Module" })), It = /* @__PURE__ */ gt(Mt);
443
+ var Le;
444
+ const { isUtf8: Ne } = S, Dt = [
445
+ 0,
446
+ 0,
447
+ 0,
448
+ 0,
449
+ 0,
450
+ 0,
451
+ 0,
452
+ 0,
453
+ 0,
454
+ 0,
455
+ 0,
456
+ 0,
457
+ 0,
458
+ 0,
459
+ 0,
460
+ 0,
461
+ // 0 - 15
462
+ 0,
463
+ 0,
464
+ 0,
465
+ 0,
466
+ 0,
467
+ 0,
468
+ 0,
469
+ 0,
470
+ 0,
471
+ 0,
472
+ 0,
473
+ 0,
474
+ 0,
475
+ 0,
476
+ 0,
477
+ 0,
478
+ // 16 - 31
479
+ 0,
480
+ 1,
481
+ 0,
482
+ 1,
483
+ 1,
484
+ 1,
485
+ 1,
486
+ 1,
487
+ 0,
488
+ 0,
489
+ 1,
490
+ 1,
491
+ 0,
492
+ 1,
493
+ 1,
494
+ 0,
495
+ // 32 - 47
496
+ 1,
497
+ 1,
498
+ 1,
499
+ 1,
500
+ 1,
501
+ 1,
502
+ 1,
503
+ 1,
504
+ 1,
505
+ 1,
506
+ 0,
507
+ 0,
508
+ 0,
509
+ 0,
510
+ 0,
511
+ 0,
512
+ // 48 - 63
513
+ 0,
514
+ 1,
515
+ 1,
516
+ 1,
517
+ 1,
518
+ 1,
519
+ 1,
520
+ 1,
521
+ 1,
522
+ 1,
523
+ 1,
524
+ 1,
525
+ 1,
526
+ 1,
527
+ 1,
528
+ 1,
529
+ // 64 - 79
530
+ 1,
531
+ 1,
532
+ 1,
533
+ 1,
534
+ 1,
535
+ 1,
536
+ 1,
537
+ 1,
538
+ 1,
539
+ 1,
540
+ 1,
541
+ 0,
542
+ 0,
543
+ 0,
544
+ 1,
545
+ 1,
546
+ // 80 - 95
547
+ 1,
548
+ 1,
549
+ 1,
550
+ 1,
551
+ 1,
552
+ 1,
553
+ 1,
554
+ 1,
555
+ 1,
556
+ 1,
557
+ 1,
558
+ 1,
559
+ 1,
560
+ 1,
561
+ 1,
562
+ 1,
563
+ // 96 - 111
564
+ 1,
565
+ 1,
566
+ 1,
567
+ 1,
568
+ 1,
569
+ 1,
570
+ 1,
571
+ 1,
572
+ 1,
573
+ 1,
574
+ 1,
575
+ 0,
576
+ 1,
577
+ 0,
578
+ 1,
579
+ 0
580
+ // 112 - 127
581
+ ];
582
+ function Wt(s) {
583
+ return s >= 1e3 && s <= 1014 && s !== 1004 && s !== 1005 && s !== 1006 || s >= 3e3 && s <= 4999;
584
+ }
585
+ function be(s) {
586
+ const e = s.length;
587
+ let t = 0;
588
+ for (; t < e; )
589
+ if (!(s[t] & 128))
590
+ t++;
591
+ else if ((s[t] & 224) === 192) {
592
+ if (t + 1 === e || (s[t + 1] & 192) !== 128 || (s[t] & 254) === 192)
593
+ return !1;
594
+ t += 2;
595
+ } else if ((s[t] & 240) === 224) {
596
+ if (t + 2 >= e || (s[t + 1] & 192) !== 128 || (s[t + 2] & 192) !== 128 || s[t] === 224 && (s[t + 1] & 224) === 128 || // Overlong
597
+ s[t] === 237 && (s[t + 1] & 224) === 160)
598
+ return !1;
599
+ t += 3;
600
+ } else if ((s[t] & 248) === 240) {
601
+ if (t + 3 >= e || (s[t + 1] & 192) !== 128 || (s[t + 2] & 192) !== 128 || (s[t + 3] & 192) !== 128 || s[t] === 240 && (s[t + 1] & 240) === 128 || // Overlong
602
+ s[t] === 244 && s[t + 1] > 143 || s[t] > 244)
603
+ return !1;
604
+ t += 4;
605
+ } else
606
+ return !1;
607
+ return !0;
608
+ }
609
+ re.exports = {
610
+ isValidStatusCode: Wt,
611
+ isValidUTF8: be,
612
+ tokenChars: Dt
613
+ };
614
+ if (Ne)
615
+ Le = re.exports.isValidUTF8 = function(s) {
616
+ return s.length < 24 ? be(s) : Ne(s);
617
+ };
618
+ else if (!process.env.WS_NO_UTF_8_VALIDATE)
619
+ try {
620
+ const s = It;
621
+ Le = re.exports.isValidUTF8 = function(e) {
622
+ return e.length < 32 ? be(e) : s(e);
623
+ };
624
+ } catch {
625
+ }
626
+ var ae = re.exports;
627
+ const { Writable: At } = S, Pe = oe, {
628
+ BINARY_TYPES: Ft,
629
+ EMPTY_BUFFER: Re,
630
+ kStatusCode: jt,
631
+ kWebSocket: Gt
632
+ } = U, { concat: de, toArrayBuffer: Vt, unmask: Ht } = ne, { isValidStatusCode: zt, isValidUTF8: Ue } = ae, X = Buffer[Symbol.species], A = 0, Be = 1, $e = 2, Me = 3, _e = 4, Yt = 5;
633
+ let qt = class extends At {
634
+ /**
635
+ * Creates a Receiver instance.
636
+ *
637
+ * @param {Object} [options] Options object
638
+ * @param {String} [options.binaryType=nodebuffer] The type for binary data
639
+ * @param {Object} [options.extensions] An object containing the negotiated
640
+ * extensions
641
+ * @param {Boolean} [options.isServer=false] Specifies whether to operate in
642
+ * client or server mode
643
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
644
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
645
+ * not to skip UTF-8 validation for text and close messages
646
+ */
647
+ constructor(e = {}) {
648
+ super(), this._binaryType = e.binaryType || Ft[0], this._extensions = e.extensions || {}, this._isServer = !!e.isServer, this._maxPayload = e.maxPayload | 0, this._skipUTF8Validation = !!e.skipUTF8Validation, this[Gt] = void 0, this._bufferedBytes = 0, this._buffers = [], this._compressed = !1, this._payloadLength = 0, this._mask = void 0, this._fragmented = 0, this._masked = !1, this._fin = !1, this._opcode = 0, this._totalPayloadLength = 0, this._messageLength = 0, this._fragments = [], this._state = A, this._loop = !1;
649
+ }
650
+ /**
651
+ * Implements `Writable.prototype._write()`.
652
+ *
653
+ * @param {Buffer} chunk The chunk of data to write
654
+ * @param {String} encoding The character encoding of `chunk`
655
+ * @param {Function} cb Callback
656
+ * @private
657
+ */
658
+ _write(e, t, r) {
659
+ if (this._opcode === 8 && this._state == A)
660
+ return r();
661
+ this._bufferedBytes += e.length, this._buffers.push(e), this.startLoop(r);
662
+ }
663
+ /**
664
+ * Consumes `n` bytes from the buffered data.
665
+ *
666
+ * @param {Number} n The number of bytes to consume
667
+ * @return {Buffer} The consumed bytes
668
+ * @private
669
+ */
670
+ consume(e) {
671
+ if (this._bufferedBytes -= e, e === this._buffers[0].length)
672
+ return this._buffers.shift();
673
+ if (e < this._buffers[0].length) {
674
+ const r = this._buffers[0];
675
+ return this._buffers[0] = new X(
676
+ r.buffer,
677
+ r.byteOffset + e,
678
+ r.length - e
679
+ ), new X(r.buffer, r.byteOffset, e);
680
+ }
681
+ const t = Buffer.allocUnsafe(e);
682
+ do {
683
+ const r = this._buffers[0], i = t.length - e;
684
+ e >= r.length ? t.set(this._buffers.shift(), i) : (t.set(new Uint8Array(r.buffer, r.byteOffset, e), i), this._buffers[0] = new X(
685
+ r.buffer,
686
+ r.byteOffset + e,
687
+ r.length - e
688
+ )), e -= r.length;
689
+ } while (e > 0);
690
+ return t;
691
+ }
692
+ /**
693
+ * Starts the parsing loop.
694
+ *
695
+ * @param {Function} cb Callback
696
+ * @private
697
+ */
698
+ startLoop(e) {
699
+ let t;
700
+ this._loop = !0;
701
+ do
702
+ switch (this._state) {
703
+ case A:
704
+ t = this.getInfo();
705
+ break;
706
+ case Be:
707
+ t = this.getPayloadLength16();
708
+ break;
709
+ case $e:
710
+ t = this.getPayloadLength64();
711
+ break;
712
+ case Me:
713
+ this.getMask();
714
+ break;
715
+ case _e:
716
+ t = this.getData(e);
717
+ break;
718
+ default:
719
+ this._loop = !1;
720
+ return;
721
+ }
722
+ while (this._loop);
723
+ e(t);
724
+ }
725
+ /**
726
+ * Reads the first two bytes of a frame.
727
+ *
728
+ * @return {(RangeError|undefined)} A possible error
729
+ * @private
730
+ */
731
+ getInfo() {
732
+ if (this._bufferedBytes < 2) {
733
+ this._loop = !1;
734
+ return;
735
+ }
736
+ const e = this.consume(2);
737
+ if (e[0] & 48)
738
+ return this._loop = !1, g(
739
+ RangeError,
740
+ "RSV2 and RSV3 must be clear",
741
+ !0,
742
+ 1002,
743
+ "WS_ERR_UNEXPECTED_RSV_2_3"
744
+ );
745
+ const t = (e[0] & 64) === 64;
746
+ if (t && !this._extensions[Pe.extensionName])
747
+ return this._loop = !1, g(
748
+ RangeError,
749
+ "RSV1 must be clear",
750
+ !0,
751
+ 1002,
752
+ "WS_ERR_UNEXPECTED_RSV_1"
753
+ );
754
+ if (this._fin = (e[0] & 128) === 128, this._opcode = e[0] & 15, this._payloadLength = e[1] & 127, this._opcode === 0) {
755
+ if (t)
756
+ return this._loop = !1, g(
757
+ RangeError,
758
+ "RSV1 must be clear",
759
+ !0,
760
+ 1002,
761
+ "WS_ERR_UNEXPECTED_RSV_1"
762
+ );
763
+ if (!this._fragmented)
764
+ return this._loop = !1, g(
765
+ RangeError,
766
+ "invalid opcode 0",
767
+ !0,
768
+ 1002,
769
+ "WS_ERR_INVALID_OPCODE"
770
+ );
771
+ this._opcode = this._fragmented;
772
+ } else if (this._opcode === 1 || this._opcode === 2) {
773
+ if (this._fragmented)
774
+ return this._loop = !1, g(
775
+ RangeError,
776
+ `invalid opcode ${this._opcode}`,
777
+ !0,
778
+ 1002,
779
+ "WS_ERR_INVALID_OPCODE"
780
+ );
781
+ this._compressed = t;
782
+ } else if (this._opcode > 7 && this._opcode < 11) {
783
+ if (!this._fin)
784
+ return this._loop = !1, g(
785
+ RangeError,
786
+ "FIN must be set",
787
+ !0,
788
+ 1002,
789
+ "WS_ERR_EXPECTED_FIN"
790
+ );
791
+ if (t)
792
+ return this._loop = !1, g(
793
+ RangeError,
794
+ "RSV1 must be clear",
795
+ !0,
796
+ 1002,
797
+ "WS_ERR_UNEXPECTED_RSV_1"
798
+ );
799
+ if (this._payloadLength > 125 || this._opcode === 8 && this._payloadLength === 1)
800
+ return this._loop = !1, g(
801
+ RangeError,
802
+ `invalid payload length ${this._payloadLength}`,
803
+ !0,
804
+ 1002,
805
+ "WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH"
806
+ );
807
+ } else
808
+ return this._loop = !1, g(
809
+ RangeError,
810
+ `invalid opcode ${this._opcode}`,
811
+ !0,
812
+ 1002,
813
+ "WS_ERR_INVALID_OPCODE"
814
+ );
815
+ if (!this._fin && !this._fragmented && (this._fragmented = this._opcode), this._masked = (e[1] & 128) === 128, this._isServer) {
816
+ if (!this._masked)
817
+ return this._loop = !1, g(
818
+ RangeError,
819
+ "MASK must be set",
820
+ !0,
821
+ 1002,
822
+ "WS_ERR_EXPECTED_MASK"
823
+ );
824
+ } else if (this._masked)
825
+ return this._loop = !1, g(
826
+ RangeError,
827
+ "MASK must be clear",
828
+ !0,
829
+ 1002,
830
+ "WS_ERR_UNEXPECTED_MASK"
831
+ );
832
+ if (this._payloadLength === 126)
833
+ this._state = Be;
834
+ else if (this._payloadLength === 127)
835
+ this._state = $e;
836
+ else
837
+ return this.haveLength();
838
+ }
839
+ /**
840
+ * Gets extended payload length (7+16).
841
+ *
842
+ * @return {(RangeError|undefined)} A possible error
843
+ * @private
844
+ */
845
+ getPayloadLength16() {
846
+ if (this._bufferedBytes < 2) {
847
+ this._loop = !1;
848
+ return;
849
+ }
850
+ return this._payloadLength = this.consume(2).readUInt16BE(0), this.haveLength();
851
+ }
852
+ /**
853
+ * Gets extended payload length (7+64).
854
+ *
855
+ * @return {(RangeError|undefined)} A possible error
856
+ * @private
857
+ */
858
+ getPayloadLength64() {
859
+ if (this._bufferedBytes < 8) {
860
+ this._loop = !1;
861
+ return;
862
+ }
863
+ const e = this.consume(8), t = e.readUInt32BE(0);
864
+ return t > Math.pow(2, 21) - 1 ? (this._loop = !1, g(
865
+ RangeError,
866
+ "Unsupported WebSocket frame: payload length > 2^53 - 1",
867
+ !1,
868
+ 1009,
869
+ "WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH"
870
+ )) : (this._payloadLength = t * Math.pow(2, 32) + e.readUInt32BE(4), this.haveLength());
871
+ }
872
+ /**
873
+ * Payload length has been read.
874
+ *
875
+ * @return {(RangeError|undefined)} A possible error
876
+ * @private
877
+ */
878
+ haveLength() {
879
+ if (this._payloadLength && this._opcode < 8 && (this._totalPayloadLength += this._payloadLength, this._totalPayloadLength > this._maxPayload && this._maxPayload > 0))
880
+ return this._loop = !1, g(
881
+ RangeError,
882
+ "Max payload size exceeded",
883
+ !1,
884
+ 1009,
885
+ "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
886
+ );
887
+ this._masked ? this._state = Me : this._state = _e;
888
+ }
889
+ /**
890
+ * Reads mask bytes.
891
+ *
892
+ * @private
893
+ */
894
+ getMask() {
895
+ if (this._bufferedBytes < 4) {
896
+ this._loop = !1;
897
+ return;
898
+ }
899
+ this._mask = this.consume(4), this._state = _e;
900
+ }
901
+ /**
902
+ * Reads data bytes.
903
+ *
904
+ * @param {Function} cb Callback
905
+ * @return {(Error|RangeError|undefined)} A possible error
906
+ * @private
907
+ */
908
+ getData(e) {
909
+ let t = Re;
910
+ if (this._payloadLength) {
911
+ if (this._bufferedBytes < this._payloadLength) {
912
+ this._loop = !1;
913
+ return;
914
+ }
915
+ t = this.consume(this._payloadLength), this._masked && this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3] && Ht(t, this._mask);
916
+ }
917
+ if (this._opcode > 7)
918
+ return this.controlMessage(t);
919
+ if (this._compressed) {
920
+ this._state = Yt, this.decompress(t, e);
921
+ return;
922
+ }
923
+ return t.length && (this._messageLength = this._totalPayloadLength, this._fragments.push(t)), this.dataMessage();
924
+ }
925
+ /**
926
+ * Decompresses data.
927
+ *
928
+ * @param {Buffer} data Compressed data
929
+ * @param {Function} cb Callback
930
+ * @private
931
+ */
932
+ decompress(e, t) {
933
+ this._extensions[Pe.extensionName].decompress(e, this._fin, (i, n) => {
934
+ if (i)
935
+ return t(i);
936
+ if (n.length) {
937
+ if (this._messageLength += n.length, this._messageLength > this._maxPayload && this._maxPayload > 0)
938
+ return t(
939
+ g(
940
+ RangeError,
941
+ "Max payload size exceeded",
942
+ !1,
943
+ 1009,
944
+ "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
945
+ )
946
+ );
947
+ this._fragments.push(n);
948
+ }
949
+ const o = this.dataMessage();
950
+ if (o)
951
+ return t(o);
952
+ this.startLoop(t);
953
+ });
954
+ }
955
+ /**
956
+ * Handles a data message.
957
+ *
958
+ * @return {(Error|undefined)} A possible error
959
+ * @private
960
+ */
961
+ dataMessage() {
962
+ if (this._fin) {
963
+ const e = this._messageLength, t = this._fragments;
964
+ if (this._totalPayloadLength = 0, this._messageLength = 0, this._fragmented = 0, this._fragments = [], this._opcode === 2) {
965
+ let r;
966
+ this._binaryType === "nodebuffer" ? r = de(t, e) : this._binaryType === "arraybuffer" ? r = Vt(de(t, e)) : r = t, this.emit("message", r, !0);
967
+ } else {
968
+ const r = de(t, e);
969
+ if (!this._skipUTF8Validation && !Ue(r))
970
+ return this._loop = !1, g(
971
+ Error,
972
+ "invalid UTF-8 sequence",
973
+ !0,
974
+ 1007,
975
+ "WS_ERR_INVALID_UTF8"
976
+ );
977
+ this.emit("message", r, !1);
978
+ }
979
+ }
980
+ this._state = A;
981
+ }
982
+ /**
983
+ * Handles a control message.
984
+ *
985
+ * @param {Buffer} data Data to handle
986
+ * @return {(Error|RangeError|undefined)} A possible error
987
+ * @private
988
+ */
989
+ controlMessage(e) {
990
+ if (this._opcode === 8)
991
+ if (this._loop = !1, e.length === 0)
992
+ this.emit("conclude", 1005, Re), this.end();
993
+ else {
994
+ const t = e.readUInt16BE(0);
995
+ if (!zt(t))
996
+ return g(
997
+ RangeError,
998
+ `invalid status code ${t}`,
999
+ !0,
1000
+ 1002,
1001
+ "WS_ERR_INVALID_CLOSE_CODE"
1002
+ );
1003
+ const r = new X(
1004
+ e.buffer,
1005
+ e.byteOffset + 2,
1006
+ e.length - 2
1007
+ );
1008
+ if (!this._skipUTF8Validation && !Ue(r))
1009
+ return g(
1010
+ Error,
1011
+ "invalid UTF-8 sequence",
1012
+ !0,
1013
+ 1007,
1014
+ "WS_ERR_INVALID_UTF8"
1015
+ );
1016
+ this.emit("conclude", t, r), this.end();
1017
+ }
1018
+ else
1019
+ this._opcode === 9 ? this.emit("ping", e) : this.emit("pong", e);
1020
+ this._state = A;
1021
+ }
1022
+ };
1023
+ var rt = qt;
1024
+ function g(s, e, t, r, i) {
1025
+ const n = new s(
1026
+ t ? `Invalid WebSocket frame: ${e}` : e
1027
+ );
1028
+ return Error.captureStackTrace(n, g), n.code = i, n[jt] = r, n;
1029
+ }
1030
+ const qs = /* @__PURE__ */ z(rt), { randomFillSync: Kt } = S, Ie = oe, { EMPTY_BUFFER: Xt } = U, { isValidStatusCode: Zt } = ae, { mask: De, toBuffer: M } = ne, x = Symbol("kByteLength"), Qt = Buffer.alloc(4);
1031
+ let Jt = class P {
1032
+ /**
1033
+ * Creates a Sender instance.
1034
+ *
1035
+ * @param {(net.Socket|tls.Socket)} socket The connection socket
1036
+ * @param {Object} [extensions] An object containing the negotiated extensions
1037
+ * @param {Function} [generateMask] The function used to generate the masking
1038
+ * key
1039
+ */
1040
+ constructor(e, t, r) {
1041
+ this._extensions = t || {}, r && (this._generateMask = r, this._maskBuffer = Buffer.alloc(4)), this._socket = e, this._firstFragment = !0, this._compress = !1, this._bufferedBytes = 0, this._deflating = !1, this._queue = [];
1042
+ }
1043
+ /**
1044
+ * Frames a piece of data according to the HyBi WebSocket protocol.
1045
+ *
1046
+ * @param {(Buffer|String)} data The data to frame
1047
+ * @param {Object} options Options object
1048
+ * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1049
+ * FIN bit
1050
+ * @param {Function} [options.generateMask] The function used to generate the
1051
+ * masking key
1052
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1053
+ * `data`
1054
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
1055
+ * key
1056
+ * @param {Number} options.opcode The opcode
1057
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1058
+ * modified
1059
+ * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1060
+ * RSV1 bit
1061
+ * @return {(Buffer|String)[]} The framed data
1062
+ * @public
1063
+ */
1064
+ static frame(e, t) {
1065
+ let r, i = !1, n = 2, o = !1;
1066
+ t.mask && (r = t.maskBuffer || Qt, t.generateMask ? t.generateMask(r) : Kt(r, 0, 4), o = (r[0] | r[1] | r[2] | r[3]) === 0, n = 6);
1067
+ let l;
1068
+ typeof e == "string" ? (!t.mask || o) && t[x] !== void 0 ? l = t[x] : (e = Buffer.from(e), l = e.length) : (l = e.length, i = t.mask && t.readOnly && !o);
1069
+ let f = l;
1070
+ l >= 65536 ? (n += 8, f = 127) : l > 125 && (n += 2, f = 126);
1071
+ const a = Buffer.allocUnsafe(i ? l + n : n);
1072
+ return a[0] = t.fin ? t.opcode | 128 : t.opcode, t.rsv1 && (a[0] |= 64), a[1] = f, f === 126 ? a.writeUInt16BE(l, 2) : f === 127 && (a[2] = a[3] = 0, a.writeUIntBE(l, 4, 6)), t.mask ? (a[1] |= 128, a[n - 4] = r[0], a[n - 3] = r[1], a[n - 2] = r[2], a[n - 1] = r[3], o ? [a, e] : i ? (De(e, r, a, n, l), [a]) : (De(e, r, e, 0, l), [a, e])) : [a, e];
1073
+ }
1074
+ /**
1075
+ * Sends a close message to the other peer.
1076
+ *
1077
+ * @param {Number} [code] The status code component of the body
1078
+ * @param {(String|Buffer)} [data] The message component of the body
1079
+ * @param {Boolean} [mask=false] Specifies whether or not to mask the message
1080
+ * @param {Function} [cb] Callback
1081
+ * @public
1082
+ */
1083
+ close(e, t, r, i) {
1084
+ let n;
1085
+ if (e === void 0)
1086
+ n = Xt;
1087
+ else {
1088
+ if (typeof e != "number" || !Zt(e))
1089
+ throw new TypeError("First argument must be a valid error code number");
1090
+ if (t === void 0 || !t.length)
1091
+ n = Buffer.allocUnsafe(2), n.writeUInt16BE(e, 0);
1092
+ else {
1093
+ const l = Buffer.byteLength(t);
1094
+ if (l > 123)
1095
+ throw new RangeError("The message must not be greater than 123 bytes");
1096
+ n = Buffer.allocUnsafe(2 + l), n.writeUInt16BE(e, 0), typeof t == "string" ? n.write(t, 2) : n.set(t, 2);
1097
+ }
1098
+ }
1099
+ const o = {
1100
+ [x]: n.length,
1101
+ fin: !0,
1102
+ generateMask: this._generateMask,
1103
+ mask: r,
1104
+ maskBuffer: this._maskBuffer,
1105
+ opcode: 8,
1106
+ readOnly: !1,
1107
+ rsv1: !1
1108
+ };
1109
+ this._deflating ? this.enqueue([this.dispatch, n, !1, o, i]) : this.sendFrame(P.frame(n, o), i);
1110
+ }
1111
+ /**
1112
+ * Sends a ping message to the other peer.
1113
+ *
1114
+ * @param {*} data The message to send
1115
+ * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1116
+ * @param {Function} [cb] Callback
1117
+ * @public
1118
+ */
1119
+ ping(e, t, r) {
1120
+ let i, n;
1121
+ if (typeof e == "string" ? (i = Buffer.byteLength(e), n = !1) : (e = M(e), i = e.length, n = M.readOnly), i > 125)
1122
+ throw new RangeError("The data size must not be greater than 125 bytes");
1123
+ const o = {
1124
+ [x]: i,
1125
+ fin: !0,
1126
+ generateMask: this._generateMask,
1127
+ mask: t,
1128
+ maskBuffer: this._maskBuffer,
1129
+ opcode: 9,
1130
+ readOnly: n,
1131
+ rsv1: !1
1132
+ };
1133
+ this._deflating ? this.enqueue([this.dispatch, e, !1, o, r]) : this.sendFrame(P.frame(e, o), r);
1134
+ }
1135
+ /**
1136
+ * Sends a pong message to the other peer.
1137
+ *
1138
+ * @param {*} data The message to send
1139
+ * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1140
+ * @param {Function} [cb] Callback
1141
+ * @public
1142
+ */
1143
+ pong(e, t, r) {
1144
+ let i, n;
1145
+ if (typeof e == "string" ? (i = Buffer.byteLength(e), n = !1) : (e = M(e), i = e.length, n = M.readOnly), i > 125)
1146
+ throw new RangeError("The data size must not be greater than 125 bytes");
1147
+ const o = {
1148
+ [x]: i,
1149
+ fin: !0,
1150
+ generateMask: this._generateMask,
1151
+ mask: t,
1152
+ maskBuffer: this._maskBuffer,
1153
+ opcode: 10,
1154
+ readOnly: n,
1155
+ rsv1: !1
1156
+ };
1157
+ this._deflating ? this.enqueue([this.dispatch, e, !1, o, r]) : this.sendFrame(P.frame(e, o), r);
1158
+ }
1159
+ /**
1160
+ * Sends a data message to the other peer.
1161
+ *
1162
+ * @param {*} data The message to send
1163
+ * @param {Object} options Options object
1164
+ * @param {Boolean} [options.binary=false] Specifies whether `data` is binary
1165
+ * or text
1166
+ * @param {Boolean} [options.compress=false] Specifies whether or not to
1167
+ * compress `data`
1168
+ * @param {Boolean} [options.fin=false] Specifies whether the fragment is the
1169
+ * last one
1170
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1171
+ * `data`
1172
+ * @param {Function} [cb] Callback
1173
+ * @public
1174
+ */
1175
+ send(e, t, r) {
1176
+ const i = this._extensions[Ie.extensionName];
1177
+ let n = t.binary ? 2 : 1, o = t.compress, l, f;
1178
+ if (typeof e == "string" ? (l = Buffer.byteLength(e), f = !1) : (e = M(e), l = e.length, f = M.readOnly), this._firstFragment ? (this._firstFragment = !1, o && i && i.params[i._isServer ? "server_no_context_takeover" : "client_no_context_takeover"] && (o = l >= i._threshold), this._compress = o) : (o = !1, n = 0), t.fin && (this._firstFragment = !0), i) {
1179
+ const a = {
1180
+ [x]: l,
1181
+ fin: t.fin,
1182
+ generateMask: this._generateMask,
1183
+ mask: t.mask,
1184
+ maskBuffer: this._maskBuffer,
1185
+ opcode: n,
1186
+ readOnly: f,
1187
+ rsv1: o
1188
+ };
1189
+ this._deflating ? this.enqueue([this.dispatch, e, this._compress, a, r]) : this.dispatch(e, this._compress, a, r);
1190
+ } else
1191
+ this.sendFrame(
1192
+ P.frame(e, {
1193
+ [x]: l,
1194
+ fin: t.fin,
1195
+ generateMask: this._generateMask,
1196
+ mask: t.mask,
1197
+ maskBuffer: this._maskBuffer,
1198
+ opcode: n,
1199
+ readOnly: f,
1200
+ rsv1: !1
1201
+ }),
1202
+ r
1203
+ );
1204
+ }
1205
+ /**
1206
+ * Dispatches a message.
1207
+ *
1208
+ * @param {(Buffer|String)} data The message to send
1209
+ * @param {Boolean} [compress=false] Specifies whether or not to compress
1210
+ * `data`
1211
+ * @param {Object} options Options object
1212
+ * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1213
+ * FIN bit
1214
+ * @param {Function} [options.generateMask] The function used to generate the
1215
+ * masking key
1216
+ * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1217
+ * `data`
1218
+ * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
1219
+ * key
1220
+ * @param {Number} options.opcode The opcode
1221
+ * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1222
+ * modified
1223
+ * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1224
+ * RSV1 bit
1225
+ * @param {Function} [cb] Callback
1226
+ * @private
1227
+ */
1228
+ dispatch(e, t, r, i) {
1229
+ if (!t) {
1230
+ this.sendFrame(P.frame(e, r), i);
1231
+ return;
1232
+ }
1233
+ const n = this._extensions[Ie.extensionName];
1234
+ this._bufferedBytes += r[x], this._deflating = !0, n.compress(e, r.fin, (o, l) => {
1235
+ if (this._socket.destroyed) {
1236
+ const f = new Error(
1237
+ "The socket was closed while data was being compressed"
1238
+ );
1239
+ typeof i == "function" && i(f);
1240
+ for (let a = 0; a < this._queue.length; a++) {
1241
+ const c = this._queue[a], h = c[c.length - 1];
1242
+ typeof h == "function" && h(f);
1243
+ }
1244
+ return;
1245
+ }
1246
+ this._bufferedBytes -= r[x], this._deflating = !1, r.readOnly = !1, this.sendFrame(P.frame(l, r), i), this.dequeue();
1247
+ });
1248
+ }
1249
+ /**
1250
+ * Executes queued send operations.
1251
+ *
1252
+ * @private
1253
+ */
1254
+ dequeue() {
1255
+ for (; !this._deflating && this._queue.length; ) {
1256
+ const e = this._queue.shift();
1257
+ this._bufferedBytes -= e[3][x], Reflect.apply(e[0], this, e.slice(1));
1258
+ }
1259
+ }
1260
+ /**
1261
+ * Enqueues a send operation.
1262
+ *
1263
+ * @param {Array} params Send operation parameters.
1264
+ * @private
1265
+ */
1266
+ enqueue(e) {
1267
+ this._bufferedBytes += e[3][x], this._queue.push(e);
1268
+ }
1269
+ /**
1270
+ * Sends a frame.
1271
+ *
1272
+ * @param {Buffer[]} list The frame to send
1273
+ * @param {Function} [cb] Callback
1274
+ * @private
1275
+ */
1276
+ sendFrame(e, t) {
1277
+ e.length === 2 ? (this._socket.cork(), this._socket.write(e[0]), this._socket.write(e[1], t), this._socket.uncork()) : this._socket.write(e[0], t);
1278
+ }
1279
+ };
1280
+ var it = Jt;
1281
+ const Ks = /* @__PURE__ */ z(it), { kForOnEventAttribute: F, kListener: pe } = U, We = Symbol("kCode"), Ae = Symbol("kData"), Fe = Symbol("kError"), je = Symbol("kMessage"), Ge = Symbol("kReason"), I = Symbol("kTarget"), Ve = Symbol("kType"), He = Symbol("kWasClean");
1282
+ class B {
1283
+ /**
1284
+ * Create a new `Event`.
1285
+ *
1286
+ * @param {String} type The name of the event
1287
+ * @throws {TypeError} If the `type` argument is not specified
1288
+ */
1289
+ constructor(e) {
1290
+ this[I] = null, this[Ve] = e;
1291
+ }
1292
+ /**
1293
+ * @type {*}
1294
+ */
1295
+ get target() {
1296
+ return this[I];
1297
+ }
1298
+ /**
1299
+ * @type {String}
1300
+ */
1301
+ get type() {
1302
+ return this[Ve];
1303
+ }
1304
+ }
1305
+ Object.defineProperty(B.prototype, "target", { enumerable: !0 });
1306
+ Object.defineProperty(B.prototype, "type", { enumerable: !0 });
1307
+ class Y extends B {
1308
+ /**
1309
+ * Create a new `CloseEvent`.
1310
+ *
1311
+ * @param {String} type The name of the event
1312
+ * @param {Object} [options] A dictionary object that allows for setting
1313
+ * attributes via object members of the same name
1314
+ * @param {Number} [options.code=0] The status code explaining why the
1315
+ * connection was closed
1316
+ * @param {String} [options.reason=''] A human-readable string explaining why
1317
+ * the connection was closed
1318
+ * @param {Boolean} [options.wasClean=false] Indicates whether or not the
1319
+ * connection was cleanly closed
1320
+ */
1321
+ constructor(e, t = {}) {
1322
+ super(e), this[We] = t.code === void 0 ? 0 : t.code, this[Ge] = t.reason === void 0 ? "" : t.reason, this[He] = t.wasClean === void 0 ? !1 : t.wasClean;
1323
+ }
1324
+ /**
1325
+ * @type {Number}
1326
+ */
1327
+ get code() {
1328
+ return this[We];
1329
+ }
1330
+ /**
1331
+ * @type {String}
1332
+ */
1333
+ get reason() {
1334
+ return this[Ge];
1335
+ }
1336
+ /**
1337
+ * @type {Boolean}
1338
+ */
1339
+ get wasClean() {
1340
+ return this[He];
1341
+ }
1342
+ }
1343
+ Object.defineProperty(Y.prototype, "code", { enumerable: !0 });
1344
+ Object.defineProperty(Y.prototype, "reason", { enumerable: !0 });
1345
+ Object.defineProperty(Y.prototype, "wasClean", { enumerable: !0 });
1346
+ class le extends B {
1347
+ /**
1348
+ * Create a new `ErrorEvent`.
1349
+ *
1350
+ * @param {String} type The name of the event
1351
+ * @param {Object} [options] A dictionary object that allows for setting
1352
+ * attributes via object members of the same name
1353
+ * @param {*} [options.error=null] The error that generated this event
1354
+ * @param {String} [options.message=''] The error message
1355
+ */
1356
+ constructor(e, t = {}) {
1357
+ super(e), this[Fe] = t.error === void 0 ? null : t.error, this[je] = t.message === void 0 ? "" : t.message;
1358
+ }
1359
+ /**
1360
+ * @type {*}
1361
+ */
1362
+ get error() {
1363
+ return this[Fe];
1364
+ }
1365
+ /**
1366
+ * @type {String}
1367
+ */
1368
+ get message() {
1369
+ return this[je];
1370
+ }
1371
+ }
1372
+ Object.defineProperty(le.prototype, "error", { enumerable: !0 });
1373
+ Object.defineProperty(le.prototype, "message", { enumerable: !0 });
1374
+ class xe extends B {
1375
+ /**
1376
+ * Create a new `MessageEvent`.
1377
+ *
1378
+ * @param {String} type The name of the event
1379
+ * @param {Object} [options] A dictionary object that allows for setting
1380
+ * attributes via object members of the same name
1381
+ * @param {*} [options.data=null] The message content
1382
+ */
1383
+ constructor(e, t = {}) {
1384
+ super(e), this[Ae] = t.data === void 0 ? null : t.data;
1385
+ }
1386
+ /**
1387
+ * @type {*}
1388
+ */
1389
+ get data() {
1390
+ return this[Ae];
1391
+ }
1392
+ }
1393
+ Object.defineProperty(xe.prototype, "data", { enumerable: !0 });
1394
+ const es = {
1395
+ /**
1396
+ * Register an event listener.
1397
+ *
1398
+ * @param {String} type A string representing the event type to listen for
1399
+ * @param {(Function|Object)} handler The listener to add
1400
+ * @param {Object} [options] An options object specifies characteristics about
1401
+ * the event listener
1402
+ * @param {Boolean} [options.once=false] A `Boolean` indicating that the
1403
+ * listener should be invoked at most once after being added. If `true`,
1404
+ * the listener would be automatically removed when invoked.
1405
+ * @public
1406
+ */
1407
+ addEventListener(s, e, t = {}) {
1408
+ for (const i of this.listeners(s))
1409
+ if (!t[F] && i[pe] === e && !i[F])
1410
+ return;
1411
+ let r;
1412
+ if (s === "message")
1413
+ r = function(n, o) {
1414
+ const l = new xe("message", {
1415
+ data: o ? n : n.toString()
1416
+ });
1417
+ l[I] = this, Z(e, this, l);
1418
+ };
1419
+ else if (s === "close")
1420
+ r = function(n, o) {
1421
+ const l = new Y("close", {
1422
+ code: n,
1423
+ reason: o.toString(),
1424
+ wasClean: this._closeFrameReceived && this._closeFrameSent
1425
+ });
1426
+ l[I] = this, Z(e, this, l);
1427
+ };
1428
+ else if (s === "error")
1429
+ r = function(n) {
1430
+ const o = new le("error", {
1431
+ error: n,
1432
+ message: n.message
1433
+ });
1434
+ o[I] = this, Z(e, this, o);
1435
+ };
1436
+ else if (s === "open")
1437
+ r = function() {
1438
+ const n = new B("open");
1439
+ n[I] = this, Z(e, this, n);
1440
+ };
1441
+ else
1442
+ return;
1443
+ r[F] = !!t[F], r[pe] = e, t.once ? this.once(s, r) : this.on(s, r);
1444
+ },
1445
+ /**
1446
+ * Remove an event listener.
1447
+ *
1448
+ * @param {String} type A string representing the event type to remove
1449
+ * @param {(Function|Object)} handler The listener to remove
1450
+ * @public
1451
+ */
1452
+ removeEventListener(s, e) {
1453
+ for (const t of this.listeners(s))
1454
+ if (t[pe] === e && !t[F]) {
1455
+ this.removeListener(s, t);
1456
+ break;
1457
+ }
1458
+ }
1459
+ };
1460
+ var ts = {
1461
+ CloseEvent: Y,
1462
+ ErrorEvent: le,
1463
+ Event: B,
1464
+ EventTarget: es,
1465
+ MessageEvent: xe
1466
+ };
1467
+ function Z(s, e, t) {
1468
+ typeof s == "object" && s.handleEvent ? s.handleEvent.call(s, t) : s.call(e, t);
1469
+ }
1470
+ const { tokenChars: j } = ae;
1471
+ function k(s, e, t) {
1472
+ s[e] === void 0 ? s[e] = [t] : s[e].push(t);
1473
+ }
1474
+ function ss(s) {
1475
+ const e = /* @__PURE__ */ Object.create(null);
1476
+ let t = /* @__PURE__ */ Object.create(null), r = !1, i = !1, n = !1, o, l, f = -1, a = -1, c = -1, h = 0;
1477
+ for (; h < s.length; h++)
1478
+ if (a = s.charCodeAt(h), o === void 0)
1479
+ if (c === -1 && j[a] === 1)
1480
+ f === -1 && (f = h);
1481
+ else if (h !== 0 && (a === 32 || a === 9))
1482
+ c === -1 && f !== -1 && (c = h);
1483
+ else if (a === 59 || a === 44) {
1484
+ if (f === -1)
1485
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1486
+ c === -1 && (c = h);
1487
+ const v = s.slice(f, c);
1488
+ a === 44 ? (k(e, v, t), t = /* @__PURE__ */ Object.create(null)) : o = v, f = c = -1;
1489
+ } else
1490
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1491
+ else if (l === void 0)
1492
+ if (c === -1 && j[a] === 1)
1493
+ f === -1 && (f = h);
1494
+ else if (a === 32 || a === 9)
1495
+ c === -1 && f !== -1 && (c = h);
1496
+ else if (a === 59 || a === 44) {
1497
+ if (f === -1)
1498
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1499
+ c === -1 && (c = h), k(t, s.slice(f, c), !0), a === 44 && (k(e, o, t), t = /* @__PURE__ */ Object.create(null), o = void 0), f = c = -1;
1500
+ } else if (a === 61 && f !== -1 && c === -1)
1501
+ l = s.slice(f, h), f = c = -1;
1502
+ else
1503
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1504
+ else if (i) {
1505
+ if (j[a] !== 1)
1506
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1507
+ f === -1 ? f = h : r || (r = !0), i = !1;
1508
+ } else if (n)
1509
+ if (j[a] === 1)
1510
+ f === -1 && (f = h);
1511
+ else if (a === 34 && f !== -1)
1512
+ n = !1, c = h;
1513
+ else if (a === 92)
1514
+ i = !0;
1515
+ else
1516
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1517
+ else if (a === 34 && s.charCodeAt(h - 1) === 61)
1518
+ n = !0;
1519
+ else if (c === -1 && j[a] === 1)
1520
+ f === -1 && (f = h);
1521
+ else if (f !== -1 && (a === 32 || a === 9))
1522
+ c === -1 && (c = h);
1523
+ else if (a === 59 || a === 44) {
1524
+ if (f === -1)
1525
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1526
+ c === -1 && (c = h);
1527
+ let v = s.slice(f, c);
1528
+ r && (v = v.replace(/\\/g, ""), r = !1), k(t, l, v), a === 44 && (k(e, o, t), t = /* @__PURE__ */ Object.create(null), o = void 0), l = void 0, f = c = -1;
1529
+ } else
1530
+ throw new SyntaxError(`Unexpected character at index ${h}`);
1531
+ if (f === -1 || n || a === 32 || a === 9)
1532
+ throw new SyntaxError("Unexpected end of input");
1533
+ c === -1 && (c = h);
1534
+ const p = s.slice(f, c);
1535
+ return o === void 0 ? k(e, p, t) : (l === void 0 ? k(t, p, !0) : r ? k(t, l, p.replace(/\\/g, "")) : k(t, l, p), k(e, o, t)), e;
1536
+ }
1537
+ function rs(s) {
1538
+ return Object.keys(s).map((e) => {
1539
+ let t = s[e];
1540
+ return Array.isArray(t) || (t = [t]), t.map((r) => [e].concat(
1541
+ Object.keys(r).map((i) => {
1542
+ let n = r[i];
1543
+ return Array.isArray(n) || (n = [n]), n.map((o) => o === !0 ? i : `${i}=${o}`).join("; ");
1544
+ })
1545
+ ).join("; ")).join(", ");
1546
+ }).join(", ");
1547
+ }
1548
+ var nt = { format: rs, parse: ss };
1549
+ const is = S, ns = S, os = S, ot = S, as = S, { randomBytes: ls, createHash: fs } = S, { URL: me } = S, T = oe, hs = rt, cs = it, {
1550
+ BINARY_TYPES: ze,
1551
+ EMPTY_BUFFER: Q,
1552
+ GUID: us,
1553
+ kForOnEventAttribute: ge,
1554
+ kListener: ds,
1555
+ kStatusCode: _s,
1556
+ kWebSocket: y,
1557
+ NOOP: at
1558
+ } = U, {
1559
+ EventTarget: { addEventListener: ps, removeEventListener: ms }
1560
+ } = ts, { format: gs, parse: ys } = nt, { toBuffer: vs } = ne, Ss = 30 * 1e3, lt = Symbol("kAborted"), ye = [8, 13], O = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"], Es = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
1561
+ let m = class d extends is {
1562
+ /**
1563
+ * Create a new `WebSocket`.
1564
+ *
1565
+ * @param {(String|URL)} address The URL to which to connect
1566
+ * @param {(String|String[])} [protocols] The subprotocols
1567
+ * @param {Object} [options] Connection options
1568
+ */
1569
+ constructor(e, t, r) {
1570
+ super(), this._binaryType = ze[0], this._closeCode = 1006, this._closeFrameReceived = !1, this._closeFrameSent = !1, this._closeMessage = Q, this._closeTimer = null, this._extensions = {}, this._paused = !1, this._protocol = "", this._readyState = d.CONNECTING, this._receiver = null, this._sender = null, this._socket = null, e !== null ? (this._bufferedAmount = 0, this._isServer = !1, this._redirects = 0, t === void 0 ? t = [] : Array.isArray(t) || (typeof t == "object" && t !== null ? (r = t, t = []) : t = [t]), ht(this, e, t, r)) : this._isServer = !0;
1571
+ }
1572
+ /**
1573
+ * This deviates from the WHATWG interface since ws doesn't support the
1574
+ * required default "blob" type (instead we define a custom "nodebuffer"
1575
+ * type).
1576
+ *
1577
+ * @type {String}
1578
+ */
1579
+ get binaryType() {
1580
+ return this._binaryType;
1581
+ }
1582
+ set binaryType(e) {
1583
+ ze.includes(e) && (this._binaryType = e, this._receiver && (this._receiver._binaryType = e));
1584
+ }
1585
+ /**
1586
+ * @type {Number}
1587
+ */
1588
+ get bufferedAmount() {
1589
+ return this._socket ? this._socket._writableState.length + this._sender._bufferedBytes : this._bufferedAmount;
1590
+ }
1591
+ /**
1592
+ * @type {String}
1593
+ */
1594
+ get extensions() {
1595
+ return Object.keys(this._extensions).join();
1596
+ }
1597
+ /**
1598
+ * @type {Boolean}
1599
+ */
1600
+ get isPaused() {
1601
+ return this._paused;
1602
+ }
1603
+ /**
1604
+ * @type {Function}
1605
+ */
1606
+ /* istanbul ignore next */
1607
+ get onclose() {
1608
+ return null;
1609
+ }
1610
+ /**
1611
+ * @type {Function}
1612
+ */
1613
+ /* istanbul ignore next */
1614
+ get onerror() {
1615
+ return null;
1616
+ }
1617
+ /**
1618
+ * @type {Function}
1619
+ */
1620
+ /* istanbul ignore next */
1621
+ get onopen() {
1622
+ return null;
1623
+ }
1624
+ /**
1625
+ * @type {Function}
1626
+ */
1627
+ /* istanbul ignore next */
1628
+ get onmessage() {
1629
+ return null;
1630
+ }
1631
+ /**
1632
+ * @type {String}
1633
+ */
1634
+ get protocol() {
1635
+ return this._protocol;
1636
+ }
1637
+ /**
1638
+ * @type {Number}
1639
+ */
1640
+ get readyState() {
1641
+ return this._readyState;
1642
+ }
1643
+ /**
1644
+ * @type {String}
1645
+ */
1646
+ get url() {
1647
+ return this._url;
1648
+ }
1649
+ /**
1650
+ * Set up the socket and the internal resources.
1651
+ *
1652
+ * @param {(net.Socket|tls.Socket)} socket The network socket between the
1653
+ * server and client
1654
+ * @param {Buffer} head The first packet of the upgraded stream
1655
+ * @param {Object} options Options object
1656
+ * @param {Function} [options.generateMask] The function used to generate the
1657
+ * masking key
1658
+ * @param {Number} [options.maxPayload=0] The maximum allowed message size
1659
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
1660
+ * not to skip UTF-8 validation for text and close messages
1661
+ * @private
1662
+ */
1663
+ setSocket(e, t, r) {
1664
+ const i = new hs({
1665
+ binaryType: this.binaryType,
1666
+ extensions: this._extensions,
1667
+ isServer: this._isServer,
1668
+ maxPayload: r.maxPayload,
1669
+ skipUTF8Validation: r.skipUTF8Validation
1670
+ });
1671
+ this._sender = new cs(e, this._extensions, r.generateMask), this._receiver = i, this._socket = e, i[y] = this, e[y] = this, i.on("conclude", ks), i.on("drain", ws), i.on("error", Os), i.on("message", Cs), i.on("ping", Ts), i.on("pong", Ls), e.setTimeout(0), e.setNoDelay(), t.length > 0 && e.unshift(t), e.on("close", ut), e.on("data", fe), e.on("end", dt), e.on("error", _t), this._readyState = d.OPEN, this.emit("open");
1672
+ }
1673
+ /**
1674
+ * Emit the `'close'` event.
1675
+ *
1676
+ * @private
1677
+ */
1678
+ emitClose() {
1679
+ if (!this._socket) {
1680
+ this._readyState = d.CLOSED, this.emit("close", this._closeCode, this._closeMessage);
1681
+ return;
1682
+ }
1683
+ this._extensions[T.extensionName] && this._extensions[T.extensionName].cleanup(), this._receiver.removeAllListeners(), this._readyState = d.CLOSED, this.emit("close", this._closeCode, this._closeMessage);
1684
+ }
1685
+ /**
1686
+ * Start a closing handshake.
1687
+ *
1688
+ * +----------+ +-----------+ +----------+
1689
+ * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
1690
+ * | +----------+ +-----------+ +----------+ |
1691
+ * +----------+ +-----------+ |
1692
+ * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
1693
+ * +----------+ +-----------+ |
1694
+ * | | | +---+ |
1695
+ * +------------------------+-->|fin| - - - -
1696
+ * | +---+ | +---+
1697
+ * - - - - -|fin|<---------------------+
1698
+ * +---+
1699
+ *
1700
+ * @param {Number} [code] Status code explaining why the connection is closing
1701
+ * @param {(String|Buffer)} [data] The reason why the connection is
1702
+ * closing
1703
+ * @public
1704
+ */
1705
+ close(e, t) {
1706
+ if (this.readyState !== d.CLOSED) {
1707
+ if (this.readyState === d.CONNECTING) {
1708
+ b(this, this._req, "WebSocket was closed before the connection was established");
1709
+ return;
1710
+ }
1711
+ if (this.readyState === d.CLOSING) {
1712
+ this._closeFrameSent && (this._closeFrameReceived || this._receiver._writableState.errorEmitted) && this._socket.end();
1713
+ return;
1714
+ }
1715
+ this._readyState = d.CLOSING, this._sender.close(e, t, !this._isServer, (r) => {
1716
+ r || (this._closeFrameSent = !0, (this._closeFrameReceived || this._receiver._writableState.errorEmitted) && this._socket.end());
1717
+ }), this._closeTimer = setTimeout(
1718
+ this._socket.destroy.bind(this._socket),
1719
+ Ss
1720
+ );
1721
+ }
1722
+ }
1723
+ /**
1724
+ * Pause the socket.
1725
+ *
1726
+ * @public
1727
+ */
1728
+ pause() {
1729
+ this.readyState === d.CONNECTING || this.readyState === d.CLOSED || (this._paused = !0, this._socket.pause());
1730
+ }
1731
+ /**
1732
+ * Send a ping.
1733
+ *
1734
+ * @param {*} [data] The data to send
1735
+ * @param {Boolean} [mask] Indicates whether or not to mask `data`
1736
+ * @param {Function} [cb] Callback which is executed when the ping is sent
1737
+ * @public
1738
+ */
1739
+ ping(e, t, r) {
1740
+ if (this.readyState === d.CONNECTING)
1741
+ throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
1742
+ if (typeof e == "function" ? (r = e, e = t = void 0) : typeof t == "function" && (r = t, t = void 0), typeof e == "number" && (e = e.toString()), this.readyState !== d.OPEN) {
1743
+ ve(this, e, r);
1744
+ return;
1745
+ }
1746
+ t === void 0 && (t = !this._isServer), this._sender.ping(e || Q, t, r);
1747
+ }
1748
+ /**
1749
+ * Send a pong.
1750
+ *
1751
+ * @param {*} [data] The data to send
1752
+ * @param {Boolean} [mask] Indicates whether or not to mask `data`
1753
+ * @param {Function} [cb] Callback which is executed when the pong is sent
1754
+ * @public
1755
+ */
1756
+ pong(e, t, r) {
1757
+ if (this.readyState === d.CONNECTING)
1758
+ throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
1759
+ if (typeof e == "function" ? (r = e, e = t = void 0) : typeof t == "function" && (r = t, t = void 0), typeof e == "number" && (e = e.toString()), this.readyState !== d.OPEN) {
1760
+ ve(this, e, r);
1761
+ return;
1762
+ }
1763
+ t === void 0 && (t = !this._isServer), this._sender.pong(e || Q, t, r);
1764
+ }
1765
+ /**
1766
+ * Resume the socket.
1767
+ *
1768
+ * @public
1769
+ */
1770
+ resume() {
1771
+ this.readyState === d.CONNECTING || this.readyState === d.CLOSED || (this._paused = !1, this._receiver._writableState.needDrain || this._socket.resume());
1772
+ }
1773
+ /**
1774
+ * Send a data message.
1775
+ *
1776
+ * @param {*} data The message to send
1777
+ * @param {Object} [options] Options object
1778
+ * @param {Boolean} [options.binary] Specifies whether `data` is binary or
1779
+ * text
1780
+ * @param {Boolean} [options.compress] Specifies whether or not to compress
1781
+ * `data`
1782
+ * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
1783
+ * last one
1784
+ * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
1785
+ * @param {Function} [cb] Callback which is executed when data is written out
1786
+ * @public
1787
+ */
1788
+ send(e, t, r) {
1789
+ if (this.readyState === d.CONNECTING)
1790
+ throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");
1791
+ if (typeof t == "function" && (r = t, t = {}), typeof e == "number" && (e = e.toString()), this.readyState !== d.OPEN) {
1792
+ ve(this, e, r);
1793
+ return;
1794
+ }
1795
+ const i = {
1796
+ binary: typeof e != "string",
1797
+ mask: !this._isServer,
1798
+ compress: !0,
1799
+ fin: !0,
1800
+ ...t
1801
+ };
1802
+ this._extensions[T.extensionName] || (i.compress = !1), this._sender.send(e || Q, i, r);
1803
+ }
1804
+ /**
1805
+ * Forcibly close the connection.
1806
+ *
1807
+ * @public
1808
+ */
1809
+ terminate() {
1810
+ if (this.readyState !== d.CLOSED) {
1811
+ if (this.readyState === d.CONNECTING) {
1812
+ b(this, this._req, "WebSocket was closed before the connection was established");
1813
+ return;
1814
+ }
1815
+ this._socket && (this._readyState = d.CLOSING, this._socket.destroy());
1816
+ }
1817
+ }
1818
+ };
1819
+ Object.defineProperty(m, "CONNECTING", {
1820
+ enumerable: !0,
1821
+ value: O.indexOf("CONNECTING")
1822
+ });
1823
+ Object.defineProperty(m.prototype, "CONNECTING", {
1824
+ enumerable: !0,
1825
+ value: O.indexOf("CONNECTING")
1826
+ });
1827
+ Object.defineProperty(m, "OPEN", {
1828
+ enumerable: !0,
1829
+ value: O.indexOf("OPEN")
1830
+ });
1831
+ Object.defineProperty(m.prototype, "OPEN", {
1832
+ enumerable: !0,
1833
+ value: O.indexOf("OPEN")
1834
+ });
1835
+ Object.defineProperty(m, "CLOSING", {
1836
+ enumerable: !0,
1837
+ value: O.indexOf("CLOSING")
1838
+ });
1839
+ Object.defineProperty(m.prototype, "CLOSING", {
1840
+ enumerable: !0,
1841
+ value: O.indexOf("CLOSING")
1842
+ });
1843
+ Object.defineProperty(m, "CLOSED", {
1844
+ enumerable: !0,
1845
+ value: O.indexOf("CLOSED")
1846
+ });
1847
+ Object.defineProperty(m.prototype, "CLOSED", {
1848
+ enumerable: !0,
1849
+ value: O.indexOf("CLOSED")
1850
+ });
1851
+ [
1852
+ "binaryType",
1853
+ "bufferedAmount",
1854
+ "extensions",
1855
+ "isPaused",
1856
+ "protocol",
1857
+ "readyState",
1858
+ "url"
1859
+ ].forEach((s) => {
1860
+ Object.defineProperty(m.prototype, s, { enumerable: !0 });
1861
+ });
1862
+ ["open", "error", "close", "message"].forEach((s) => {
1863
+ Object.defineProperty(m.prototype, `on${s}`, {
1864
+ enumerable: !0,
1865
+ get() {
1866
+ for (const e of this.listeners(s))
1867
+ if (e[ge])
1868
+ return e[ds];
1869
+ return null;
1870
+ },
1871
+ set(e) {
1872
+ for (const t of this.listeners(s))
1873
+ if (t[ge]) {
1874
+ this.removeListener(s, t);
1875
+ break;
1876
+ }
1877
+ typeof e == "function" && this.addEventListener(s, e, {
1878
+ [ge]: !0
1879
+ });
1880
+ }
1881
+ });
1882
+ });
1883
+ m.prototype.addEventListener = ps;
1884
+ m.prototype.removeEventListener = ms;
1885
+ var ft = m;
1886
+ function ht(s, e, t, r) {
1887
+ const i = {
1888
+ protocolVersion: ye[1],
1889
+ maxPayload: 104857600,
1890
+ skipUTF8Validation: !1,
1891
+ perMessageDeflate: !0,
1892
+ followRedirects: !1,
1893
+ maxRedirects: 10,
1894
+ ...r,
1895
+ createConnection: void 0,
1896
+ socketPath: void 0,
1897
+ hostname: void 0,
1898
+ protocol: void 0,
1899
+ timeout: void 0,
1900
+ method: "GET",
1901
+ host: void 0,
1902
+ path: void 0,
1903
+ port: void 0
1904
+ };
1905
+ if (!ye.includes(i.protocolVersion))
1906
+ throw new RangeError(
1907
+ `Unsupported protocol version: ${i.protocolVersion} (supported versions: ${ye.join(", ")})`
1908
+ );
1909
+ let n;
1910
+ if (e instanceof me)
1911
+ n = e, s._url = e.href;
1912
+ else {
1913
+ try {
1914
+ n = new me(e);
1915
+ } catch {
1916
+ throw new SyntaxError(`Invalid URL: ${e}`);
1917
+ }
1918
+ s._url = e;
1919
+ }
1920
+ const o = n.protocol === "wss:", l = n.protocol === "ws+unix:";
1921
+ let f;
1922
+ if (n.protocol !== "ws:" && !o && !l ? f = `The URL's protocol must be one of "ws:", "wss:", or "ws+unix:"` : l && !n.pathname ? f = "The URL's pathname is empty" : n.hash && (f = "The URL contains a fragment identifier"), f) {
1923
+ const u = new SyntaxError(f);
1924
+ if (s._redirects === 0)
1925
+ throw u;
1926
+ ee(s, u);
1927
+ return;
1928
+ }
1929
+ const a = o ? 443 : 80, c = ls(16).toString("base64"), h = o ? ns.request : os.request, p = /* @__PURE__ */ new Set();
1930
+ let v;
1931
+ if (i.createConnection = o ? xs : bs, i.defaultPort = i.defaultPort || a, i.port = n.port || a, i.host = n.hostname.startsWith("[") ? n.hostname.slice(1, -1) : n.hostname, i.headers = {
1932
+ ...i.headers,
1933
+ "Sec-WebSocket-Version": i.protocolVersion,
1934
+ "Sec-WebSocket-Key": c,
1935
+ Connection: "Upgrade",
1936
+ Upgrade: "websocket"
1937
+ }, i.path = n.pathname + n.search, i.timeout = i.handshakeTimeout, i.perMessageDeflate && (v = new T(
1938
+ i.perMessageDeflate !== !0 ? i.perMessageDeflate : {},
1939
+ !1,
1940
+ i.maxPayload
1941
+ ), i.headers["Sec-WebSocket-Extensions"] = gs({
1942
+ [T.extensionName]: v.offer()
1943
+ })), t.length) {
1944
+ for (const u of t) {
1945
+ if (typeof u != "string" || !Es.test(u) || p.has(u))
1946
+ throw new SyntaxError(
1947
+ "An invalid or duplicated subprotocol was specified"
1948
+ );
1949
+ p.add(u);
1950
+ }
1951
+ i.headers["Sec-WebSocket-Protocol"] = t.join(",");
1952
+ }
1953
+ if (i.origin && (i.protocolVersion < 13 ? i.headers["Sec-WebSocket-Origin"] = i.origin : i.headers.Origin = i.origin), (n.username || n.password) && (i.auth = `${n.username}:${n.password}`), l) {
1954
+ const u = i.path.split(":");
1955
+ i.socketPath = u[0], i.path = u[1];
1956
+ }
1957
+ let _;
1958
+ if (i.followRedirects) {
1959
+ if (s._redirects === 0) {
1960
+ s._originalIpc = l, s._originalSecure = o, s._originalHostOrSocketPath = l ? i.socketPath : n.host;
1961
+ const u = r && r.headers;
1962
+ if (r = { ...r, headers: {} }, u)
1963
+ for (const [E, $] of Object.entries(u))
1964
+ r.headers[E.toLowerCase()] = $;
1965
+ } else if (s.listenerCount("redirect") === 0) {
1966
+ const u = l ? s._originalIpc ? i.socketPath === s._originalHostOrSocketPath : !1 : s._originalIpc ? !1 : n.host === s._originalHostOrSocketPath;
1967
+ (!u || s._originalSecure && !o) && (delete i.headers.authorization, delete i.headers.cookie, u || delete i.headers.host, i.auth = void 0);
1968
+ }
1969
+ i.auth && !r.headers.authorization && (r.headers.authorization = "Basic " + Buffer.from(i.auth).toString("base64")), _ = s._req = h(i), s._redirects && s.emit("redirect", s.url, _);
1970
+ } else
1971
+ _ = s._req = h(i);
1972
+ i.timeout && _.on("timeout", () => {
1973
+ b(s, _, "Opening handshake has timed out");
1974
+ }), _.on("error", (u) => {
1975
+ _ === null || _[lt] || (_ = s._req = null, ee(s, u));
1976
+ }), _.on("response", (u) => {
1977
+ const E = u.headers.location, $ = u.statusCode;
1978
+ if (E && i.followRedirects && $ >= 300 && $ < 400) {
1979
+ if (++s._redirects > i.maxRedirects) {
1980
+ b(s, _, "Maximum redirects exceeded");
1981
+ return;
1982
+ }
1983
+ _.abort();
1984
+ let q;
1985
+ try {
1986
+ q = new me(E, e);
1987
+ } catch {
1988
+ const L = new SyntaxError(`Invalid URL: ${E}`);
1989
+ ee(s, L);
1990
+ return;
1991
+ }
1992
+ ht(s, q, t, r);
1993
+ } else
1994
+ s.emit("unexpected-response", _, u) || b(
1995
+ s,
1996
+ _,
1997
+ `Unexpected server response: ${u.statusCode}`
1998
+ );
1999
+ }), _.on("upgrade", (u, E, $) => {
2000
+ if (s.emit("upgrade", u), s.readyState !== m.CONNECTING)
2001
+ return;
2002
+ if (_ = s._req = null, u.headers.upgrade.toLowerCase() !== "websocket") {
2003
+ b(s, E, "Invalid Upgrade header");
2004
+ return;
2005
+ }
2006
+ const q = fs("sha1").update(c + us).digest("base64");
2007
+ if (u.headers["sec-websocket-accept"] !== q) {
2008
+ b(s, E, "Invalid Sec-WebSocket-Accept header");
2009
+ return;
2010
+ }
2011
+ const D = u.headers["sec-websocket-protocol"];
2012
+ let L;
2013
+ if (D !== void 0 ? p.size ? p.has(D) || (L = "Server sent an invalid subprotocol") : L = "Server sent a subprotocol but none was requested" : p.size && (L = "Server sent no subprotocol"), L) {
2014
+ b(s, E, L);
2015
+ return;
2016
+ }
2017
+ D && (s._protocol = D);
2018
+ const ke = u.headers["sec-websocket-extensions"];
2019
+ if (ke !== void 0) {
2020
+ if (!v) {
2021
+ b(s, E, "Server sent a Sec-WebSocket-Extensions header but no extension was requested");
2022
+ return;
2023
+ }
2024
+ let he;
2025
+ try {
2026
+ he = ys(ke);
2027
+ } catch {
2028
+ b(s, E, "Invalid Sec-WebSocket-Extensions header");
2029
+ return;
2030
+ }
2031
+ const we = Object.keys(he);
2032
+ if (we.length !== 1 || we[0] !== T.extensionName) {
2033
+ b(s, E, "Server indicated an extension that was not requested");
2034
+ return;
2035
+ }
2036
+ try {
2037
+ v.accept(he[T.extensionName]);
2038
+ } catch {
2039
+ b(s, E, "Invalid Sec-WebSocket-Extensions header");
2040
+ return;
2041
+ }
2042
+ s._extensions[T.extensionName] = v;
2043
+ }
2044
+ s.setSocket(E, $, {
2045
+ generateMask: i.generateMask,
2046
+ maxPayload: i.maxPayload,
2047
+ skipUTF8Validation: i.skipUTF8Validation
2048
+ });
2049
+ }), i.finishRequest ? i.finishRequest(_, s) : _.end();
2050
+ }
2051
+ function ee(s, e) {
2052
+ s._readyState = m.CLOSING, s.emit("error", e), s.emitClose();
2053
+ }
2054
+ function bs(s) {
2055
+ return s.path = s.socketPath, ot.connect(s);
2056
+ }
2057
+ function xs(s) {
2058
+ return s.path = void 0, !s.servername && s.servername !== "" && (s.servername = ot.isIP(s.host) ? "" : s.host), as.connect(s);
2059
+ }
2060
+ function b(s, e, t) {
2061
+ s._readyState = m.CLOSING;
2062
+ const r = new Error(t);
2063
+ Error.captureStackTrace(r, b), e.setHeader ? (e[lt] = !0, e.abort(), e.socket && !e.socket.destroyed && e.socket.destroy(), process.nextTick(ee, s, r)) : (e.destroy(r), e.once("error", s.emit.bind(s, "error")), e.once("close", s.emitClose.bind(s)));
2064
+ }
2065
+ function ve(s, e, t) {
2066
+ if (e) {
2067
+ const r = vs(e).length;
2068
+ s._socket ? s._sender._bufferedBytes += r : s._bufferedAmount += r;
2069
+ }
2070
+ if (t) {
2071
+ const r = new Error(
2072
+ `WebSocket is not open: readyState ${s.readyState} (${O[s.readyState]})`
2073
+ );
2074
+ process.nextTick(t, r);
2075
+ }
2076
+ }
2077
+ function ks(s, e) {
2078
+ const t = this[y];
2079
+ t._closeFrameReceived = !0, t._closeMessage = e, t._closeCode = s, t._socket[y] !== void 0 && (t._socket.removeListener("data", fe), process.nextTick(ct, t._socket), s === 1005 ? t.close() : t.close(s, e));
2080
+ }
2081
+ function ws() {
2082
+ const s = this[y];
2083
+ s.isPaused || s._socket.resume();
2084
+ }
2085
+ function Os(s) {
2086
+ const e = this[y];
2087
+ e._socket[y] !== void 0 && (e._socket.removeListener("data", fe), process.nextTick(ct, e._socket), e.close(s[_s])), e.emit("error", s);
2088
+ }
2089
+ function Ye() {
2090
+ this[y].emitClose();
2091
+ }
2092
+ function Cs(s, e) {
2093
+ this[y].emit("message", s, e);
2094
+ }
2095
+ function Ts(s) {
2096
+ const e = this[y];
2097
+ e.pong(s, !e._isServer, at), e.emit("ping", s);
2098
+ }
2099
+ function Ls(s) {
2100
+ this[y].emit("pong", s);
2101
+ }
2102
+ function ct(s) {
2103
+ s.resume();
2104
+ }
2105
+ function ut() {
2106
+ const s = this[y];
2107
+ this.removeListener("close", ut), this.removeListener("data", fe), this.removeListener("end", dt), s._readyState = m.CLOSING;
2108
+ let e;
2109
+ !this._readableState.endEmitted && !s._closeFrameReceived && !s._receiver._writableState.errorEmitted && (e = s._socket.read()) !== null && s._receiver.write(e), s._receiver.end(), this[y] = void 0, clearTimeout(s._closeTimer), s._receiver._writableState.finished || s._receiver._writableState.errorEmitted ? s.emitClose() : (s._receiver.on("error", Ye), s._receiver.on("finish", Ye));
2110
+ }
2111
+ function fe(s) {
2112
+ this[y]._receiver.write(s) || this.pause();
2113
+ }
2114
+ function dt() {
2115
+ const s = this[y];
2116
+ s._readyState = m.CLOSING, s._receiver.end(), this.end();
2117
+ }
2118
+ function _t() {
2119
+ const s = this[y];
2120
+ this.removeListener("error", _t), this.on("error", at), s && (s._readyState = m.CLOSING, this.destroy());
2121
+ }
2122
+ const Xs = /* @__PURE__ */ z(ft), { tokenChars: Ns } = ae;
2123
+ function Ps(s) {
2124
+ const e = /* @__PURE__ */ new Set();
2125
+ let t = -1, r = -1, i = 0;
2126
+ for (i; i < s.length; i++) {
2127
+ const o = s.charCodeAt(i);
2128
+ if (r === -1 && Ns[o] === 1)
2129
+ t === -1 && (t = i);
2130
+ else if (i !== 0 && (o === 32 || o === 9))
2131
+ r === -1 && t !== -1 && (r = i);
2132
+ else if (o === 44) {
2133
+ if (t === -1)
2134
+ throw new SyntaxError(`Unexpected character at index ${i}`);
2135
+ r === -1 && (r = i);
2136
+ const l = s.slice(t, r);
2137
+ if (e.has(l))
2138
+ throw new SyntaxError(`The "${l}" subprotocol is duplicated`);
2139
+ e.add(l), t = r = -1;
2140
+ } else
2141
+ throw new SyntaxError(`Unexpected character at index ${i}`);
2142
+ }
2143
+ if (t === -1 || r !== -1)
2144
+ throw new SyntaxError("Unexpected end of input");
2145
+ const n = s.slice(t, i);
2146
+ if (e.has(n))
2147
+ throw new SyntaxError(`The "${n}" subprotocol is duplicated`);
2148
+ return e.add(n), e;
2149
+ }
2150
+ var Rs = { parse: Ps };
2151
+ const Us = S, ie = S, { createHash: Bs } = S, qe = nt, N = oe, $s = Rs, Ms = ft, { GUID: Is, kWebSocket: Ds } = U, Ws = /^[+/0-9A-Za-z]{22}==$/, Ke = 0, Xe = 1, pt = 2;
2152
+ class As extends Us {
2153
+ /**
2154
+ * Create a `WebSocketServer` instance.
2155
+ *
2156
+ * @param {Object} options Configuration options
2157
+ * @param {Number} [options.backlog=511] The maximum length of the queue of
2158
+ * pending connections
2159
+ * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
2160
+ * track clients
2161
+ * @param {Function} [options.handleProtocols] A hook to handle protocols
2162
+ * @param {String} [options.host] The hostname where to bind the server
2163
+ * @param {Number} [options.maxPayload=104857600] The maximum allowed message
2164
+ * size
2165
+ * @param {Boolean} [options.noServer=false] Enable no server mode
2166
+ * @param {String} [options.path] Accept only connections matching this path
2167
+ * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
2168
+ * permessage-deflate
2169
+ * @param {Number} [options.port] The port where to bind the server
2170
+ * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
2171
+ * server to use
2172
+ * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
2173
+ * not to skip UTF-8 validation for text and close messages
2174
+ * @param {Function} [options.verifyClient] A hook to reject connections
2175
+ * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
2176
+ * class to use. It must be the `WebSocket` class or class that extends it
2177
+ * @param {Function} [callback] A listener for the `listening` event
2178
+ */
2179
+ constructor(e, t) {
2180
+ if (super(), e = {
2181
+ maxPayload: 100 * 1024 * 1024,
2182
+ skipUTF8Validation: !1,
2183
+ perMessageDeflate: !1,
2184
+ handleProtocols: null,
2185
+ clientTracking: !0,
2186
+ verifyClient: null,
2187
+ noServer: !1,
2188
+ backlog: null,
2189
+ // use default (511 as implemented in net.js)
2190
+ server: null,
2191
+ host: null,
2192
+ path: null,
2193
+ port: null,
2194
+ WebSocket: Ms,
2195
+ ...e
2196
+ }, e.port == null && !e.server && !e.noServer || e.port != null && (e.server || e.noServer) || e.server && e.noServer)
2197
+ throw new TypeError(
2198
+ 'One and only one of the "port", "server", or "noServer" options must be specified'
2199
+ );
2200
+ if (e.port != null ? (this._server = ie.createServer((r, i) => {
2201
+ const n = ie.STATUS_CODES[426];
2202
+ i.writeHead(426, {
2203
+ "Content-Length": n.length,
2204
+ "Content-Type": "text/plain"
2205
+ }), i.end(n);
2206
+ }), this._server.listen(
2207
+ e.port,
2208
+ e.host,
2209
+ e.backlog,
2210
+ t
2211
+ )) : e.server && (this._server = e.server), this._server) {
2212
+ const r = this.emit.bind(this, "connection");
2213
+ this._removeListeners = js(this._server, {
2214
+ listening: this.emit.bind(this, "listening"),
2215
+ error: this.emit.bind(this, "error"),
2216
+ upgrade: (i, n, o) => {
2217
+ this.handleUpgrade(i, n, o, r);
2218
+ }
2219
+ });
2220
+ }
2221
+ e.perMessageDeflate === !0 && (e.perMessageDeflate = {}), e.clientTracking && (this.clients = /* @__PURE__ */ new Set(), this._shouldEmitClose = !1), this.options = e, this._state = Ke;
2222
+ }
2223
+ /**
2224
+ * Returns the bound address, the address family name, and port of the server
2225
+ * as reported by the operating system if listening on an IP socket.
2226
+ * If the server is listening on a pipe or UNIX domain socket, the name is
2227
+ * returned as a string.
2228
+ *
2229
+ * @return {(Object|String|null)} The address of the server
2230
+ * @public
2231
+ */
2232
+ address() {
2233
+ if (this.options.noServer)
2234
+ throw new Error('The server is operating in "noServer" mode');
2235
+ return this._server ? this._server.address() : null;
2236
+ }
2237
+ /**
2238
+ * Stop the server from accepting new connections and emit the `'close'` event
2239
+ * when all existing connections are closed.
2240
+ *
2241
+ * @param {Function} [cb] A one-time listener for the `'close'` event
2242
+ * @public
2243
+ */
2244
+ close(e) {
2245
+ if (this._state === pt) {
2246
+ e && this.once("close", () => {
2247
+ e(new Error("The server is not running"));
2248
+ }), process.nextTick(G, this);
2249
+ return;
2250
+ }
2251
+ if (e && this.once("close", e), this._state !== Xe)
2252
+ if (this._state = Xe, this.options.noServer || this.options.server)
2253
+ this._server && (this._removeListeners(), this._removeListeners = this._server = null), this.clients ? this.clients.size ? this._shouldEmitClose = !0 : process.nextTick(G, this) : process.nextTick(G, this);
2254
+ else {
2255
+ const t = this._server;
2256
+ this._removeListeners(), this._removeListeners = this._server = null, t.close(() => {
2257
+ G(this);
2258
+ });
2259
+ }
2260
+ }
2261
+ /**
2262
+ * See if a given request should be handled by this server instance.
2263
+ *
2264
+ * @param {http.IncomingMessage} req Request object to inspect
2265
+ * @return {Boolean} `true` if the request is valid, else `false`
2266
+ * @public
2267
+ */
2268
+ shouldHandle(e) {
2269
+ if (this.options.path) {
2270
+ const t = e.url.indexOf("?");
2271
+ if ((t !== -1 ? e.url.slice(0, t) : e.url) !== this.options.path)
2272
+ return !1;
2273
+ }
2274
+ return !0;
2275
+ }
2276
+ /**
2277
+ * Handle a HTTP Upgrade request.
2278
+ *
2279
+ * @param {http.IncomingMessage} req The request object
2280
+ * @param {(net.Socket|tls.Socket)} socket The network socket between the
2281
+ * server and client
2282
+ * @param {Buffer} head The first packet of the upgraded stream
2283
+ * @param {Function} cb Callback
2284
+ * @public
2285
+ */
2286
+ handleUpgrade(e, t, r, i) {
2287
+ t.on("error", Ze);
2288
+ const n = e.headers["sec-websocket-key"], o = +e.headers["sec-websocket-version"];
2289
+ if (e.method !== "GET") {
2290
+ R(this, e, t, 405, "Invalid HTTP method");
2291
+ return;
2292
+ }
2293
+ if (e.headers.upgrade.toLowerCase() !== "websocket") {
2294
+ R(this, e, t, 400, "Invalid Upgrade header");
2295
+ return;
2296
+ }
2297
+ if (!n || !Ws.test(n)) {
2298
+ R(this, e, t, 400, "Missing or invalid Sec-WebSocket-Key header");
2299
+ return;
2300
+ }
2301
+ if (o !== 8 && o !== 13) {
2302
+ R(this, e, t, 400, "Missing or invalid Sec-WebSocket-Version header");
2303
+ return;
2304
+ }
2305
+ if (!this.shouldHandle(e)) {
2306
+ H(t, 400);
2307
+ return;
2308
+ }
2309
+ const l = e.headers["sec-websocket-protocol"];
2310
+ let f = /* @__PURE__ */ new Set();
2311
+ if (l !== void 0)
2312
+ try {
2313
+ f = $s.parse(l);
2314
+ } catch {
2315
+ R(this, e, t, 400, "Invalid Sec-WebSocket-Protocol header");
2316
+ return;
2317
+ }
2318
+ const a = e.headers["sec-websocket-extensions"], c = {};
2319
+ if (this.options.perMessageDeflate && a !== void 0) {
2320
+ const h = new N(
2321
+ this.options.perMessageDeflate,
2322
+ !0,
2323
+ this.options.maxPayload
2324
+ );
2325
+ try {
2326
+ const p = qe.parse(a);
2327
+ p[N.extensionName] && (h.accept(p[N.extensionName]), c[N.extensionName] = h);
2328
+ } catch {
2329
+ R(this, e, t, 400, "Invalid or unacceptable Sec-WebSocket-Extensions header");
2330
+ return;
2331
+ }
2332
+ }
2333
+ if (this.options.verifyClient) {
2334
+ const h = {
2335
+ origin: e.headers[`${o === 8 ? "sec-websocket-origin" : "origin"}`],
2336
+ secure: !!(e.socket.authorized || e.socket.encrypted),
2337
+ req: e
2338
+ };
2339
+ if (this.options.verifyClient.length === 2) {
2340
+ this.options.verifyClient(h, (p, v, _, u) => {
2341
+ if (!p)
2342
+ return H(t, v || 401, _, u);
2343
+ this.completeUpgrade(
2344
+ c,
2345
+ n,
2346
+ f,
2347
+ e,
2348
+ t,
2349
+ r,
2350
+ i
2351
+ );
2352
+ });
2353
+ return;
2354
+ }
2355
+ if (!this.options.verifyClient(h))
2356
+ return H(t, 401);
2357
+ }
2358
+ this.completeUpgrade(c, n, f, e, t, r, i);
2359
+ }
2360
+ /**
2361
+ * Upgrade the connection to WebSocket.
2362
+ *
2363
+ * @param {Object} extensions The accepted extensions
2364
+ * @param {String} key The value of the `Sec-WebSocket-Key` header
2365
+ * @param {Set} protocols The subprotocols
2366
+ * @param {http.IncomingMessage} req The request object
2367
+ * @param {(net.Socket|tls.Socket)} socket The network socket between the
2368
+ * server and client
2369
+ * @param {Buffer} head The first packet of the upgraded stream
2370
+ * @param {Function} cb Callback
2371
+ * @throws {Error} If called more than once with the same socket
2372
+ * @private
2373
+ */
2374
+ completeUpgrade(e, t, r, i, n, o, l) {
2375
+ if (!n.readable || !n.writable)
2376
+ return n.destroy();
2377
+ if (n[Ds])
2378
+ throw new Error(
2379
+ "server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration"
2380
+ );
2381
+ if (this._state > Ke)
2382
+ return H(n, 503);
2383
+ const a = [
2384
+ "HTTP/1.1 101 Switching Protocols",
2385
+ "Upgrade: websocket",
2386
+ "Connection: Upgrade",
2387
+ `Sec-WebSocket-Accept: ${Bs("sha1").update(t + Is).digest("base64")}`
2388
+ ], c = new this.options.WebSocket(null);
2389
+ if (r.size) {
2390
+ const h = this.options.handleProtocols ? this.options.handleProtocols(r, i) : r.values().next().value;
2391
+ h && (a.push(`Sec-WebSocket-Protocol: ${h}`), c._protocol = h);
2392
+ }
2393
+ if (e[N.extensionName]) {
2394
+ const h = e[N.extensionName].params, p = qe.format({
2395
+ [N.extensionName]: [h]
2396
+ });
2397
+ a.push(`Sec-WebSocket-Extensions: ${p}`), c._extensions = e;
2398
+ }
2399
+ this.emit("headers", a, i), n.write(a.concat(`\r
2400
+ `).join(`\r
2401
+ `)), n.removeListener("error", Ze), c.setSocket(n, o, {
2402
+ maxPayload: this.options.maxPayload,
2403
+ skipUTF8Validation: this.options.skipUTF8Validation
2404
+ }), this.clients && (this.clients.add(c), c.on("close", () => {
2405
+ this.clients.delete(c), this._shouldEmitClose && !this.clients.size && process.nextTick(G, this);
2406
+ })), l(c, i);
2407
+ }
2408
+ }
2409
+ var Fs = As;
2410
+ function js(s, e) {
2411
+ for (const t of Object.keys(e))
2412
+ s.on(t, e[t]);
2413
+ return function() {
2414
+ for (const r of Object.keys(e))
2415
+ s.removeListener(r, e[r]);
2416
+ };
2417
+ }
2418
+ function G(s) {
2419
+ s._state = pt, s.emit("close");
2420
+ }
2421
+ function Ze() {
2422
+ this.destroy();
2423
+ }
2424
+ function H(s, e, t, r) {
2425
+ t = t || ie.STATUS_CODES[e], r = {
2426
+ Connection: "close",
2427
+ "Content-Type": "text/html",
2428
+ "Content-Length": Buffer.byteLength(t),
2429
+ ...r
2430
+ }, s.once("finish", s.destroy), s.end(
2431
+ `HTTP/1.1 ${e} ${ie.STATUS_CODES[e]}\r
2432
+ ` + Object.keys(r).map((i) => `${i}: ${r[i]}`).join(`\r
2433
+ `) + `\r
2434
+ \r
2435
+ ` + t
2436
+ );
2437
+ }
2438
+ function R(s, e, t, r, i) {
2439
+ if (s.listenerCount("wsClientError")) {
2440
+ const n = new Error(i);
2441
+ Error.captureStackTrace(n, R), s.emit("wsClientError", n, t, e);
2442
+ } else
2443
+ H(t, r, i);
2444
+ }
2445
+ const Zs = /* @__PURE__ */ z(Fs);
2446
+ export {
2447
+ qs as Receiver,
2448
+ Ks as Sender,
2449
+ Xs as WebSocket,
2450
+ Zs as WebSocketServer,
2451
+ Vs as createWebSocketStream,
2452
+ Xs as default
2453
+ };
gradio_dualvision/gradio_patches/templates/example/index.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const {
2
+ SvelteComponent: y,
3
+ append: m,
4
+ attr: n,
5
+ detach: b,
6
+ element: u,
7
+ init: k,
8
+ insert: p,
9
+ noop: w,
10
+ safe_not_equal: h,
11
+ space: o,
12
+ src_url_equal: v,
13
+ toggle_class: f
14
+ } = window.__gradio__svelte__internal;
15
+ function q(a) {
16
+ let e, l, _, g, i, c, s, d;
17
+ return {
18
+ c() {
19
+ e = u("div"), l = u("img"), g = o(), i = u("img"), s = o(), d = u("span"), v(l.src, _ = /*samples_dir*/
20
+ a[1] + /*value*/
21
+ a[0][0]) || n(l, "src", _), n(l, "class", "svelte-l4wpk0"), v(i.src, c = /*samples_dir*/
22
+ a[1] + /*value*/
23
+ a[0][1]) || n(i, "src", c), n(i, "class", "svelte-l4wpk0"), n(d, "class", "svelte-l4wpk0"), n(e, "class", "wrap svelte-l4wpk0"), f(
24
+ e,
25
+ "table",
26
+ /*type*/
27
+ a[2] === "table"
28
+ ), f(
29
+ e,
30
+ "gallery",
31
+ /*type*/
32
+ a[2] === "gallery"
33
+ ), f(
34
+ e,
35
+ "selected",
36
+ /*selected*/
37
+ a[3]
38
+ );
39
+ },
40
+ m(t, r) {
41
+ p(t, e, r), m(e, l), m(e, g), m(e, i), m(e, s), m(e, d);
42
+ },
43
+ p(t, [r]) {
44
+ r & /*samples_dir, value*/
45
+ 3 && !v(l.src, _ = /*samples_dir*/
46
+ t[1] + /*value*/
47
+ t[0][0]) && n(l, "src", _), r & /*samples_dir, value*/
48
+ 3 && !v(i.src, c = /*samples_dir*/
49
+ t[1] + /*value*/
50
+ t[0][1]) && n(i, "src", c), r & /*type*/
51
+ 4 && f(
52
+ e,
53
+ "table",
54
+ /*type*/
55
+ t[2] === "table"
56
+ ), r & /*type*/
57
+ 4 && f(
58
+ e,
59
+ "gallery",
60
+ /*type*/
61
+ t[2] === "gallery"
62
+ ), r & /*selected*/
63
+ 8 && f(
64
+ e,
65
+ "selected",
66
+ /*selected*/
67
+ t[3]
68
+ );
69
+ },
70
+ i: w,
71
+ o: w,
72
+ d(t) {
73
+ t && b(e);
74
+ }
75
+ };
76
+ }
77
+ function I(a, e, l) {
78
+ let { value: _ } = e, { samples_dir: g } = e, { type: i } = e, { selected: c = !1 } = e;
79
+ return a.$$set = (s) => {
80
+ "value" in s && l(0, _ = s.value), "samples_dir" in s && l(1, g = s.samples_dir), "type" in s && l(2, i = s.type), "selected" in s && l(3, c = s.selected);
81
+ }, [_, g, i, c];
82
+ }
83
+ class C extends y {
84
+ constructor(e) {
85
+ super(), k(this, e, I, q, h, {
86
+ value: 0,
87
+ samples_dir: 1,
88
+ type: 2,
89
+ selected: 3
90
+ });
91
+ }
92
+ }
93
+ export {
94
+ C as default
95
+ };
gradio_dualvision/gradio_patches/templates/example/style.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .wrap.svelte-l4wpk0.svelte-l4wpk0{position:relative;height:var(--size-64);width:var(--size-40);overflow:hidden;border-radius:var(--radius-lg)}img.svelte-l4wpk0.svelte-l4wpk0{height:var(--size-64);width:var(--size-40);position:absolute;object-fit:cover}.wrap.selected.svelte-l4wpk0.svelte-l4wpk0{border-color:var(--color-accent)}.wrap.svelte-l4wpk0 img.svelte-l4wpk0:first-child{clip-path:inset(0 50% 0 0%)}.wrap.svelte-l4wpk0 img.svelte-l4wpk0:nth-of-type(2){clip-path:inset(0 0 0 50%)}span.svelte-l4wpk0.svelte-l4wpk0{position:absolute;top:0;left:calc(50% - .75px);height:var(--size-64);width:1.5px;background:var(--border-color-primary)}.table.svelte-l4wpk0.svelte-l4wpk0{margin:0 auto;border:2px solid var(--border-color-primary);border-radius:var(--radius-lg)}.gallery.svelte-l4wpk0.svelte-l4wpk0{border:2px solid var(--border-color-primary);object-fit:cover}
gradio_dualvision/version.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023-2025 Marigold Team, ETH Zürich. All rights reserved.
2
+ # This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
3
+ # See https://creativecommons.org/licenses/by-sa/4.0/ for details.
4
+ # --------------------------------------------------------------------------
5
+ # DualVision is a Gradio template app for image processing. It was developed
6
+ # to support the Marigold project. If you find this code useful, we kindly
7
+ # ask you to cite our most relevant papers.
8
+ # More information about Marigold:
9
+ # https://marigoldmonodepth.github.io
10
+ # https://marigoldcomputervision.github.io
11
+ # Efficient inference pipelines are now part of diffusers:
12
+ # https://huggingface.co/docs/diffusers/using-diffusers/marigold_usage
13
+ # https://huggingface.co/docs/diffusers/api/pipelines/marigold
14
+ # Examples of trained models and live demos:
15
+ # https://huggingface.co/prs-eth
16
+ # Related projects:
17
+ # https://marigolddepthcompletion.github.io/
18
+ # https://rollingdepth.github.io/
19
+ # Citation (BibTeX):
20
+ # https://github.com/prs-eth/Marigold#-citation
21
+ # https://github.com/prs-eth/Marigold-DC#-citation
22
+ # https://github.com/prs-eth/rollingdepth#-citation
23
+ # --------------------------------------------------------------------------
24
+
25
+ __version__ = "0.1.0"
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio==4.44.1
2
+ gradio_imageslider==0.0.20
3
+ spaces
setup.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ import os
3
+
4
+ from setuptools import setup, find_packages
5
+
6
+ with open(os.path.join("gradio_dualvision", "version.py")) as f:
7
+ version_pycode = f.read()
8
+ exec(version_pycode)
9
+
10
+ with open("requirements.txt") as f:
11
+ requirements = f.read().splitlines()
12
+
13
+ setup(
14
+ name="gradio_dualvision",
15
+ version=__version__,
16
+ author="Anton Obukhov",
17
+ description="A Python package for dual-vision processing in Gradio.",
18
+ url="https://github.com/toshas/gradio-dualvision",
19
+ license="Apache-2.0",
20
+ packages=find_packages(include=["gradio_dualvision", "gradio_dualvision.*"]),
21
+ install_requires=requirements,
22
+ python_requires=">=3.8",
23
+ include_package_data=True,
24
+ )