@gradio/annotatedimage 0.7.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,267 @@
1
+ <script>import { onMount } from "svelte";
2
+ import { Block, BlockLabel, Empty, IconButton } from "@gradio/atoms";
3
+ import { Image, Maximize, Minimize } from "@gradio/icons";
4
+ import { StatusTracker } from "@gradio/statustracker";
5
+ import {} from "@gradio/client";
6
+ import { resolve_wasm_src } from "@gradio/wasm/svelte";
7
+ export let elem_id = "";
8
+ export let elem_classes = [];
9
+ export let visible = true;
10
+ export let value = null;
11
+ let old_value = null;
12
+ let _value = null;
13
+ export let gradio;
14
+ export let label = gradio.i18n("annotated_image.annotated_image");
15
+ export let show_label = true;
16
+ export let show_legend = true;
17
+ export let height;
18
+ export let width;
19
+ export let color_map;
20
+ export let container = true;
21
+ export let scale = null;
22
+ export let min_width = void 0;
23
+ let active = null;
24
+ export let loading_status;
25
+ export let show_fullscreen_button = true;
26
+ let is_full_screen = false;
27
+ let image_container;
28
+ onMount(() => {
29
+ document.addEventListener("fullscreenchange", () => {
30
+ is_full_screen = !!document.fullscreenElement;
31
+ });
32
+ });
33
+ const toggle_full_screen = async () => {
34
+ if (!is_full_screen) {
35
+ await image_container.requestFullscreen();
36
+ } else {
37
+ await document.exitFullscreen();
38
+ }
39
+ };
40
+ let latest_promise = null;
41
+ $: {
42
+ if (value !== old_value) {
43
+ old_value = value;
44
+ gradio.dispatch("change");
45
+ }
46
+ if (value) {
47
+ const normalized_value = {
48
+ image: value.image,
49
+ annotations: value.annotations.map((ann) => ({
50
+ image: ann.image,
51
+ label: ann.label
52
+ }))
53
+ };
54
+ _value = normalized_value;
55
+ const image_url_promise = resolve_wasm_src(normalized_value.image.url);
56
+ const annotation_urls_promise = Promise.all(
57
+ normalized_value.annotations.map(
58
+ (ann) => resolve_wasm_src(ann.image.url)
59
+ )
60
+ );
61
+ const current_promise = Promise.all([
62
+ image_url_promise,
63
+ annotation_urls_promise
64
+ ]);
65
+ latest_promise = current_promise;
66
+ current_promise.then(([image_url, annotation_urls]) => {
67
+ if (latest_promise !== current_promise) {
68
+ return;
69
+ }
70
+ const async_resolved_value = {
71
+ image: {
72
+ ...normalized_value.image,
73
+ url: image_url ?? void 0
74
+ },
75
+ annotations: normalized_value.annotations.map((ann, i) => ({
76
+ ...ann,
77
+ image: {
78
+ ...ann.image,
79
+ url: annotation_urls[i] ?? void 0
80
+ }
81
+ }))
82
+ };
83
+ _value = async_resolved_value;
84
+ });
85
+ } else {
86
+ _value = null;
87
+ }
88
+ }
89
+ function handle_mouseover(_label) {
90
+ active = _label;
91
+ }
92
+ function handle_mouseout() {
93
+ active = null;
94
+ }
95
+ function handle_click(i, value2) {
96
+ gradio.dispatch("select", {
97
+ value: label,
98
+ index: i
99
+ });
100
+ }
101
+ </script>
102
+
103
+ <Block
104
+ {visible}
105
+ {elem_id}
106
+ {elem_classes}
107
+ padding={false}
108
+ {height}
109
+ {width}
110
+ allow_overflow={false}
111
+ {container}
112
+ {scale}
113
+ {min_width}
114
+ >
115
+ <StatusTracker
116
+ autoscroll={gradio.autoscroll}
117
+ i18n={gradio.i18n}
118
+ {...loading_status}
119
+ />
120
+ <BlockLabel
121
+ {show_label}
122
+ Icon={Image}
123
+ label={label || gradio.i18n("image.image")}
124
+ />
125
+
126
+ <div class="container">
127
+ {#if _value == null}
128
+ <Empty size="large" unpadded_box={true}><Image /></Empty>
129
+ {:else}
130
+ <div class="image-container" bind:this={image_container}>
131
+ <div class="icon-buttons">
132
+ {#if !is_full_screen && show_fullscreen_button}
133
+ <IconButton
134
+ Icon={Maximize}
135
+ label="View in full screen"
136
+ on:click={toggle_full_screen}
137
+ />
138
+ {/if}
139
+
140
+ {#if is_full_screen}
141
+ <IconButton
142
+ Icon={Minimize}
143
+ label="Exit full screen"
144
+ on:click={toggle_full_screen}
145
+ />
146
+ {/if}
147
+ </div>
148
+
149
+ <img
150
+ class="base-image"
151
+ class:fit-height={height && !is_full_screen}
152
+ src={_value ? _value.image.url : null}
153
+ alt="the base file that is annotated"
154
+ />
155
+ {#each _value ? _value?.annotations : [] as ann, i}
156
+ <img
157
+ alt="segmentation mask identifying {label} within the uploaded file"
158
+ class="mask fit-height"
159
+ class:fit-height={!is_full_screen}
160
+ class:active={active == ann.label}
161
+ class:inactive={active != ann.label && active != null}
162
+ src={ann.image.url}
163
+ style={color_map && ann.label in color_map
164
+ ? null
165
+ : `filter: hue-rotate(${Math.round(
166
+ (i * 360) / _value?.annotations.length
167
+ )}deg);`}
168
+ />
169
+ {/each}
170
+ </div>
171
+ {#if show_legend && _value}
172
+ <div class="legend">
173
+ {#each _value.annotations as ann, i}
174
+ <button
175
+ class="legend-item"
176
+ style="background-color: {color_map && ann.label in color_map
177
+ ? color_map[ann.label] + '88'
178
+ : `hsla(${Math.round(
179
+ (i * 360) / _value.annotations.length
180
+ )}, 100%, 50%, 0.3)`}"
181
+ on:mouseover={() => handle_mouseover(ann.label)}
182
+ on:focus={() => handle_mouseover(ann.label)}
183
+ on:mouseout={() => handle_mouseout()}
184
+ on:blur={() => handle_mouseout()}
185
+ on:click={() => handle_click(i, ann.label)}
186
+ >
187
+ {ann.label}
188
+ </button>
189
+ {/each}
190
+ </div>
191
+ {/if}
192
+ {/if}
193
+ </div>
194
+ </Block>
195
+
196
+ <style>
197
+ .base-image {
198
+ display: block;
199
+ width: 100%;
200
+ height: auto;
201
+ }
202
+ .container {
203
+ display: flex;
204
+ position: relative;
205
+ flex-direction: column;
206
+ justify-content: center;
207
+ align-items: center;
208
+ width: var(--size-full);
209
+ height: var(--size-full);
210
+ }
211
+ .image-container {
212
+ position: relative;
213
+ top: 0;
214
+ left: 0;
215
+ flex-grow: 1;
216
+ width: 100%;
217
+ overflow: hidden;
218
+ }
219
+ .fit-height {
220
+ top: 0;
221
+ left: 0;
222
+ width: 100%;
223
+ height: 100%;
224
+ object-fit: contain;
225
+ }
226
+ .mask {
227
+ opacity: 0.85;
228
+ transition: all 0.2s ease-in-out;
229
+ position: absolute;
230
+ }
231
+ .image-container:hover .mask {
232
+ opacity: 0.3;
233
+ }
234
+ .mask.active {
235
+ opacity: 1;
236
+ }
237
+ .mask.inactive {
238
+ opacity: 0;
239
+ }
240
+ .legend {
241
+ display: flex;
242
+ flex-direction: row;
243
+ flex-wrap: wrap;
244
+ align-content: center;
245
+ justify-content: center;
246
+ align-items: center;
247
+ gap: var(--spacing-sm);
248
+ padding: var(--spacing-sm);
249
+ }
250
+ .legend-item {
251
+ display: flex;
252
+ flex-direction: row;
253
+ align-items: center;
254
+ cursor: pointer;
255
+ border-radius: var(--radius-sm);
256
+ padding: var(--spacing-sm);
257
+ }
258
+
259
+ .icon-buttons {
260
+ display: flex;
261
+ position: absolute;
262
+ top: 6px;
263
+ right: 6px;
264
+ gap: var(--size-1);
265
+ z-index: 1;
266
+ }
267
+ </style>
@@ -0,0 +1,43 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { Gradio, SelectData } from "@gradio/utils";
3
+ import type { LoadingStatus } from "@gradio/statustracker";
4
+ import { type FileData } from "@gradio/client";
5
+ declare const __propDef: {
6
+ props: {
7
+ elem_id?: string | undefined;
8
+ elem_classes?: string[] | undefined;
9
+ visible?: boolean | undefined;
10
+ value?: ({
11
+ image: FileData;
12
+ annotations: {
13
+ image: FileData;
14
+ label: string;
15
+ }[] | [];
16
+ } | null) | undefined;
17
+ gradio: Gradio<{
18
+ change: undefined;
19
+ select: SelectData;
20
+ }>;
21
+ label?: any;
22
+ show_label?: boolean | undefined;
23
+ show_legend?: boolean | undefined;
24
+ height: number | undefined;
25
+ width: number | undefined;
26
+ color_map: Record<string, string>;
27
+ container?: boolean | undefined;
28
+ scale?: (number | null) | undefined;
29
+ min_width?: number | undefined;
30
+ loading_status: LoadingStatus;
31
+ show_fullscreen_button?: boolean | undefined;
32
+ };
33
+ events: {
34
+ [evt: string]: CustomEvent<any>;
35
+ };
36
+ slots: {};
37
+ };
38
+ export type IndexProps = typeof __propDef.props;
39
+ export type IndexEvents = typeof __propDef.events;
40
+ export type IndexSlots = typeof __propDef.slots;
41
+ export default class Index extends SvelteComponent<IndexProps, IndexEvents, IndexSlots> {
42
+ }
43
+ export {};
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@gradio/annotatedimage",
3
+ "version": "0.7.2-beta.1",
4
+ "description": "Gradio UI packages",
5
+ "type": "module",
6
+ "author": "",
7
+ "license": "ISC",
8
+ "private": false,
9
+ "main_changeset": true,
10
+ "exports": {
11
+ ".": {
12
+ "gradio": "./Index.svelte",
13
+ "svelte": "./dist/Index.svelte",
14
+ "types": "./dist/Index.svelte.d.ts"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "devDependencies": {
19
+ "@gradio/preview": "^0.11.1-beta.0"
20
+ },
21
+ "peerDependencies": {
22
+ "svelte": "^4.0.0"
23
+ },
24
+ "dependencies": {
25
+ "@gradio/atoms": "^0.8.1-beta.1",
26
+ "@gradio/icons": "^0.8.0-beta.1",
27
+ "@gradio/upload": "^0.12.4-beta.1",
28
+ "@gradio/client": "^1.6.0-beta.1",
29
+ "@gradio/statustracker": "^0.8.0-beta.1",
30
+ "@gradio/wasm": "^0.13.1-beta.1",
31
+ "@gradio/utils": "^0.7.0-beta.1"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/gradio-app/gradio.git",
36
+ "directory": "js/annotatedimage"
37
+ }
38
+ }