@annotorious/annotorious 3.0.0-rc.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.
- package/README.md +6 -0
- package/dist/Annotorious.d.ts +15 -0
- package/dist/Annotorious.d.ts.map +1 -0
- package/dist/AnnotoriousOpts.d.ts +14 -0
- package/dist/AnnotoriousOpts.d.ts.map +1 -0
- package/dist/annotation/SVGAnnotationLayer.svelte.d.ts +1 -0
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts +11 -0
- package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts.map +1 -0
- package/dist/annotation/Transform.d.ts +6 -0
- package/dist/annotation/Transform.d.ts.map +1 -0
- package/dist/annotation/editors/Editor.svelte.d.ts +1 -0
- package/dist/annotation/editors/EditorMount.svelte.d.ts +1 -0
- package/dist/annotation/editors/Handle.d.ts +14 -0
- package/dist/annotation/editors/Handle.d.ts.map +1 -0
- package/dist/annotation/editors/editorsRegistry.d.ts +5 -0
- package/dist/annotation/editors/editorsRegistry.d.ts.map +1 -0
- package/dist/annotation/editors/index.d.ts +7 -0
- package/dist/annotation/editors/index.d.ts.map +1 -0
- package/dist/annotation/editors/polygon/PolygonEditor.svelte.d.ts +1 -0
- package/dist/annotation/editors/polygon/index.d.ts +2 -0
- package/dist/annotation/editors/polygon/index.d.ts.map +1 -0
- package/dist/annotation/editors/rectangle/RectangleEditor.svelte.d.ts +1 -0
- package/dist/annotation/editors/rectangle/index.d.ts +2 -0
- package/dist/annotation/editors/rectangle/index.d.ts.map +1 -0
- package/dist/annotation/index.d.ts +7 -0
- package/dist/annotation/index.d.ts.map +1 -0
- package/dist/annotation/shapes/Ellipse.svelte.d.ts +1 -0
- package/dist/annotation/shapes/Polygon.svelte.d.ts +1 -0
- package/dist/annotation/shapes/Rectangle.svelte.d.ts +1 -0
- package/dist/annotation/shapes/index.d.ts +4 -0
- package/dist/annotation/shapes/index.d.ts.map +1 -0
- package/dist/annotation/tools/DrawingToolConfig.d.ts +8 -0
- package/dist/annotation/tools/DrawingToolConfig.d.ts.map +1 -0
- package/dist/annotation/tools/ToolMount.svelte.d.ts +1 -0
- package/dist/annotation/tools/drawingToolsRegistry.d.ts +17 -0
- package/dist/annotation/tools/drawingToolsRegistry.d.ts.map +1 -0
- package/dist/annotation/tools/index.d.ts +5 -0
- package/dist/annotation/tools/index.d.ts.map +1 -0
- package/dist/annotation/tools/polygon/RubberbandPolygon.svelte.d.ts +1 -0
- package/dist/annotation/tools/polygon/index.d.ts +2 -0
- package/dist/annotation/tools/polygon/index.d.ts.map +1 -0
- package/dist/annotation/tools/rectangle/RubberbandRectangle.svelte.d.ts +1 -0
- package/dist/annotation/tools/rectangle/index.d.ts +2 -0
- package/dist/annotation/tools/rectangle/index.d.ts.map +1 -0
- package/dist/annotation/utils/index.d.ts +4 -0
- package/dist/annotation/utils/index.d.ts.map +1 -0
- package/dist/annotation/utils/math.d.ts +2 -0
- package/dist/annotation/utils/math.d.ts.map +1 -0
- package/dist/annotation/utils/responsive.d.ts +5 -0
- package/dist/annotation/utils/responsive.d.ts.map +1 -0
- package/dist/annotation/utils/styling.d.ts +4 -0
- package/dist/annotation/utils/styling.d.ts.map +1 -0
- package/dist/annotation/utils/touch.d.ts +2 -0
- package/dist/annotation/utils/touch.d.ts.map +1 -0
- package/dist/annotorious.css +1 -0
- package/dist/annotorious.es.js +3890 -0
- package/dist/annotorious.es.js.map +1 -0
- package/dist/annotorious.js +2 -0
- package/dist/annotorious.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/model/core/ImageAnnotation.d.ts +9 -0
- package/dist/model/core/ImageAnnotation.d.ts.map +1 -0
- package/dist/model/core/Shape.d.ts +20 -0
- package/dist/model/core/Shape.d.ts.map +1 -0
- package/dist/model/core/ellipse/Ellipse.d.ts +12 -0
- package/dist/model/core/ellipse/Ellipse.d.ts.map +1 -0
- package/dist/model/core/ellipse/ellipseUtils.d.ts +2 -0
- package/dist/model/core/ellipse/ellipseUtils.d.ts.map +1 -0
- package/dist/model/core/ellipse/index.d.ts +3 -0
- package/dist/model/core/ellipse/index.d.ts.map +1 -0
- package/dist/model/core/index.d.ts +7 -0
- package/dist/model/core/index.d.ts.map +1 -0
- package/dist/model/core/polygon/Polygon.d.ts +9 -0
- package/dist/model/core/polygon/Polygon.d.ts.map +1 -0
- package/dist/model/core/polygon/index.d.ts +3 -0
- package/dist/model/core/polygon/index.d.ts.map +1 -0
- package/dist/model/core/polygon/polygonUtils.d.ts +2 -0
- package/dist/model/core/polygon/polygonUtils.d.ts.map +1 -0
- package/dist/model/core/rectangle/Rectangle.d.ts +12 -0
- package/dist/model/core/rectangle/Rectangle.d.ts.map +1 -0
- package/dist/model/core/rectangle/index.d.ts +3 -0
- package/dist/model/core/rectangle/index.d.ts.map +1 -0
- package/dist/model/core/rectangle/rectangleUtils.d.ts +4 -0
- package/dist/model/core/rectangle/rectangleUtils.d.ts.map +1 -0
- package/dist/model/core/shapeUtils.d.ts +35 -0
- package/dist/model/core/shapeUtils.d.ts.map +1 -0
- package/dist/model/index.d.ts +3 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts +7 -0
- package/dist/model/w3c/W3CImageFormatAdapter.d.ts.map +1 -0
- package/dist/model/w3c/fragment/FragmentSelector.d.ts +10 -0
- package/dist/model/w3c/fragment/FragmentSelector.d.ts.map +1 -0
- package/dist/model/w3c/fragment/index.d.ts +2 -0
- package/dist/model/w3c/fragment/index.d.ts.map +1 -0
- package/dist/model/w3c/index.d.ts +4 -0
- package/dist/model/w3c/index.d.ts.map +1 -0
- package/dist/model/w3c/svg/SVG.d.ts +5 -0
- package/dist/model/w3c/svg/SVG.d.ts.map +1 -0
- package/dist/model/w3c/svg/SVGSelector.d.ts +9 -0
- package/dist/model/w3c/svg/SVGSelector.d.ts.map +1 -0
- package/dist/model/w3c/svg/index.d.ts +2 -0
- package/dist/model/w3c/svg/index.d.ts.map +1 -0
- package/dist/state/ImageAnnotationStore.d.ts +11 -0
- package/dist/state/ImageAnnotationStore.d.ts.map +1 -0
- package/dist/state/ImageAnnotatorState.d.ts +12 -0
- package/dist/state/ImageAnnotatorState.d.ts.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/spatialTree.d.ts +21 -0
- package/dist/state/spatialTree.d.ts.map +1 -0
- package/dist/themes/index.d.ts +2 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/smart/index.d.ts +2 -0
- package/dist/themes/smart/index.d.ts.map +1 -0
- package/dist/themes/smart/setTheme.d.ts +3 -0
- package/dist/themes/smart/setTheme.d.ts.map +1 -0
- package/package.json +55 -0
- package/src/Annotorious.css +74 -0
- package/src/Annotorious.ts +158 -0
- package/src/AnnotoriousOpts.ts +40 -0
- package/src/annotation/SVGAnnotationLayer.svelte +169 -0
- package/src/annotation/SVGAnnotationLayerPointerEvent.ts +55 -0
- package/src/annotation/Transform.ts +24 -0
- package/src/annotation/editors/Editor.svelte +61 -0
- package/src/annotation/editors/EditorMount.svelte +44 -0
- package/src/annotation/editors/Handle.ts +21 -0
- package/src/annotation/editors/editorsRegistry.ts +14 -0
- package/src/annotation/editors/index.ts +7 -0
- package/src/annotation/editors/polygon/PolygonEditor.svelte +64 -0
- package/src/annotation/editors/polygon/index.ts +1 -0
- package/src/annotation/editors/rectangle/RectangleEditor.svelte +143 -0
- package/src/annotation/editors/rectangle/index.ts +1 -0
- package/src/annotation/index.ts +7 -0
- package/src/annotation/shapes/Ellipse.svelte +32 -0
- package/src/annotation/shapes/Polygon.svelte +26 -0
- package/src/annotation/shapes/Rectangle.svelte +32 -0
- package/src/annotation/shapes/index.ts +3 -0
- package/src/annotation/tools/DrawingToolConfig.ts +9 -0
- package/src/annotation/tools/ToolMount.svelte +49 -0
- package/src/annotation/tools/drawingToolsRegistry.ts +26 -0
- package/src/annotation/tools/index.ts +4 -0
- package/src/annotation/tools/polygon/RubberbandPolygon.svelte +165 -0
- package/src/annotation/tools/polygon/index.ts +1 -0
- package/src/annotation/tools/rectangle/RubberbandRectangle.svelte +131 -0
- package/src/annotation/tools/rectangle/index.ts +1 -0
- package/src/annotation/utils/index.ts +3 -0
- package/src/annotation/utils/math.ts +6 -0
- package/src/annotation/utils/responsive.ts +56 -0
- package/src/annotation/utils/styling.ts +19 -0
- package/src/annotation/utils/touch.ts +1 -0
- package/src/index.ts +20 -0
- package/src/model/core/ImageAnnotation.ts +14 -0
- package/src/model/core/Shape.ts +37 -0
- package/src/model/core/ellipse/Ellipse.ts +21 -0
- package/src/model/core/ellipse/ellipseUtils.ts +28 -0
- package/src/model/core/ellipse/index.ts +2 -0
- package/src/model/core/index.ts +6 -0
- package/src/model/core/polygon/Polygon.ts +15 -0
- package/src/model/core/polygon/index.ts +2 -0
- package/src/model/core/polygon/polygonUtils.ts +43 -0
- package/src/model/core/rectangle/Rectangle.ts +21 -0
- package/src/model/core/rectangle/index.ts +2 -0
- package/src/model/core/rectangle/rectangleUtils.ts +17 -0
- package/src/model/core/shapeUtils.ts +57 -0
- package/src/model/index.ts +2 -0
- package/src/model/w3c/W3CImageFormatAdapter.ts +83 -0
- package/src/model/w3c/fragment/FragmentSelector.ts +59 -0
- package/src/model/w3c/fragment/index.ts +1 -0
- package/src/model/w3c/index.ts +3 -0
- package/src/model/w3c/svg/SVG.ts +36 -0
- package/src/model/w3c/svg/SVGSelector.ts +99 -0
- package/src/model/w3c/svg/index.ts +1 -0
- package/src/state/ImageAnnotationStore.ts +18 -0
- package/src/state/ImageAnnotatorState.ts +88 -0
- package/src/state/index.ts +2 -0
- package/src/state/spatialTree.ts +108 -0
- package/src/themes/dark/index.css +24 -0
- package/src/themes/index.ts +1 -0
- package/src/themes/light/index.css +30 -0
- package/src/themes/smart/index.ts +1 -0
- package/src/themes/smart/setTheme.ts +46 -0
- package/src/vite-env.d.ts +2 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Store, SvelteAnnotatorState, SvelteStore } from '@annotorious/core';
|
|
2
|
+
import type { ImageAnnotation } from '../model';
|
|
3
|
+
|
|
4
|
+
export type ImageAnnotationStore = Store<ImageAnnotation> & {
|
|
5
|
+
|
|
6
|
+
getAt(x: number, y: number): ImageAnnotation | undefined;
|
|
7
|
+
|
|
8
|
+
getIntersecting(x: number, y: number, width: number, height: number): ImageAnnotation[];
|
|
9
|
+
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type SvelteImageAnnotationStore = SvelteStore<ImageAnnotation> & ImageAnnotationStore;
|
|
13
|
+
|
|
14
|
+
export type SvelteImageAnnotatorState = SvelteAnnotatorState<ImageAnnotation> & {
|
|
15
|
+
|
|
16
|
+
store: SvelteImageAnnotationStore;
|
|
17
|
+
|
|
18
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { ImageAnnotation, ImageAnnotationTarget } from '../model';
|
|
2
|
+
import type { AnnotoriousOpts } from '../AnnotoriousOpts';
|
|
3
|
+
import { createSpatialTree } from './spatialTree';
|
|
4
|
+
import {
|
|
5
|
+
createViewportState,
|
|
6
|
+
toSvelteStore,
|
|
7
|
+
type AnnotatorState,
|
|
8
|
+
type HoverState,
|
|
9
|
+
type SelectionState
|
|
10
|
+
} from '@annotorious/core';
|
|
11
|
+
import {
|
|
12
|
+
createHoverState,
|
|
13
|
+
createSelectionState,
|
|
14
|
+
createStore
|
|
15
|
+
} from '@annotorious/core';
|
|
16
|
+
import type {
|
|
17
|
+
ImageAnnotationStore,
|
|
18
|
+
SvelteImageAnnotationStore,
|
|
19
|
+
SvelteImageAnnotatorState
|
|
20
|
+
} from './ImageAnnotationStore';
|
|
21
|
+
|
|
22
|
+
export type ImageAnnotatorState<T extends ImageAnnotationStore = ImageAnnotationStore> = AnnotatorState<ImageAnnotation> & {
|
|
23
|
+
|
|
24
|
+
store: T;
|
|
25
|
+
|
|
26
|
+
selection: SelectionState<ImageAnnotation>;
|
|
27
|
+
|
|
28
|
+
hover: HoverState<ImageAnnotation>;
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const createImageAnnotatorState = <E extends unknown>(
|
|
33
|
+
opts: AnnotoriousOpts<ImageAnnotation, E>
|
|
34
|
+
): ImageAnnotatorState<ImageAnnotationStore> => {
|
|
35
|
+
|
|
36
|
+
const store = createStore<ImageAnnotation>();
|
|
37
|
+
|
|
38
|
+
const tree = createSpatialTree();
|
|
39
|
+
|
|
40
|
+
const selection = createSelectionState(store, opts.pointerSelectAction);
|
|
41
|
+
|
|
42
|
+
const hover = createHoverState(store);
|
|
43
|
+
|
|
44
|
+
const viewport = createViewportState();
|
|
45
|
+
|
|
46
|
+
store.observe(({ changes }) => {
|
|
47
|
+
tree.set(changes.created.map(a => a.target as ImageAnnotationTarget), false);
|
|
48
|
+
|
|
49
|
+
changes.deleted.forEach(a => tree.remove(a.target as ImageAnnotationTarget));
|
|
50
|
+
|
|
51
|
+
changes.updated.forEach(({ oldValue, newValue }) =>
|
|
52
|
+
tree.update(oldValue.target, newValue.target));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const getAt = (x: number, y: number): ImageAnnotation | undefined => {
|
|
56
|
+
const target = tree.getAt(x, y);
|
|
57
|
+
return target ? store.getAnnotation(target.annotation) : undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const getIntersecting = (x: number, y: number, width: number, height: number) =>
|
|
61
|
+
tree.getIntersecting(x, y, width, height).map(target => store.getAnnotation(target.annotation));
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
store: {
|
|
65
|
+
...store,
|
|
66
|
+
getAt,
|
|
67
|
+
getIntersecting
|
|
68
|
+
} as ImageAnnotationStore,
|
|
69
|
+
selection,
|
|
70
|
+
hover,
|
|
71
|
+
viewport
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const createSvelteImageAnnotatorState = <E extends unknown>(
|
|
77
|
+
opts: AnnotoriousOpts<ImageAnnotation, E>
|
|
78
|
+
): SvelteImageAnnotatorState => {
|
|
79
|
+
|
|
80
|
+
const state = createImageAnnotatorState(opts);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
...state,
|
|
84
|
+
store: toSvelteStore(state.store) as SvelteImageAnnotationStore
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import RBush from 'rbush';
|
|
2
|
+
import { ShapeType,computeArea, intersects } from '../model';
|
|
3
|
+
import type { ImageAnnotationTarget } from '../model';
|
|
4
|
+
|
|
5
|
+
interface IndexedTarget {
|
|
6
|
+
|
|
7
|
+
minX: number;
|
|
8
|
+
|
|
9
|
+
minY: number;
|
|
10
|
+
|
|
11
|
+
maxX: number;
|
|
12
|
+
|
|
13
|
+
maxY: number;
|
|
14
|
+
|
|
15
|
+
target: ImageAnnotationTarget;
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const createSpatialTree = () => {
|
|
20
|
+
|
|
21
|
+
const tree = new RBush<IndexedTarget>();
|
|
22
|
+
|
|
23
|
+
const index = new Map<string, IndexedTarget>();
|
|
24
|
+
|
|
25
|
+
const all = () => [...index.values()];
|
|
26
|
+
|
|
27
|
+
const clear = () => {
|
|
28
|
+
tree.clear();
|
|
29
|
+
index.clear();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const insert = (target: ImageAnnotationTarget) => {
|
|
33
|
+
const { minX, minY, maxX, maxY } = target.selector.geometry.bounds;
|
|
34
|
+
|
|
35
|
+
const t = { minX, minY, maxX, maxY, target };
|
|
36
|
+
|
|
37
|
+
tree.insert(t);
|
|
38
|
+
index.set(target.annotation, t);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const remove = (target: ImageAnnotationTarget) => {
|
|
42
|
+
const item = index.get(target.annotation);
|
|
43
|
+
tree.remove(item);
|
|
44
|
+
index.delete(target.annotation);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const update = (previous: ImageAnnotationTarget, updated: ImageAnnotationTarget) => {
|
|
48
|
+
remove(previous);
|
|
49
|
+
insert(updated);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const set = (targets: ImageAnnotationTarget[], replace: boolean = true) => {
|
|
53
|
+
if (replace)
|
|
54
|
+
clear();
|
|
55
|
+
|
|
56
|
+
const indexedTargets = targets.map(target => {
|
|
57
|
+
const { minX, minY, maxX, maxY } = target.selector.geometry.bounds;
|
|
58
|
+
return { minX, minY, maxX, maxY, target };
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
indexedTargets.forEach(t => index.set(t.target.annotation, t));
|
|
62
|
+
tree.load(indexedTargets);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const getAt = (x: number, y: number): ImageAnnotationTarget | null => {
|
|
66
|
+
const idxHits = tree.search({
|
|
67
|
+
minX: x,
|
|
68
|
+
minY: y,
|
|
69
|
+
maxX: x,
|
|
70
|
+
maxY: y
|
|
71
|
+
}).map(item => item.target);
|
|
72
|
+
|
|
73
|
+
// Exact hit test on shape (not needed for rectangles!)
|
|
74
|
+
const exactHits = idxHits.filter(target => {
|
|
75
|
+
return (target.selector.type === ShapeType.RECTANGLE) ||
|
|
76
|
+
intersects(target.selector, x, y);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Get smallest shape
|
|
80
|
+
if (exactHits.length > 0) {
|
|
81
|
+
exactHits.sort((a, b) => computeArea(a.selector) - computeArea(b.selector));
|
|
82
|
+
return exactHits[0];
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const getIntersecting = (x: number, y: number, width: number, height: number) =>
|
|
87
|
+
tree.search({
|
|
88
|
+
minX: x,
|
|
89
|
+
minY: y,
|
|
90
|
+
maxX: x + width,
|
|
91
|
+
maxY: y + height
|
|
92
|
+
}).map(item => item.target);
|
|
93
|
+
|
|
94
|
+
const size = () => tree.all().length;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
all,
|
|
98
|
+
clear,
|
|
99
|
+
getAt,
|
|
100
|
+
getIntersecting,
|
|
101
|
+
insert,
|
|
102
|
+
remove,
|
|
103
|
+
set,
|
|
104
|
+
size,
|
|
105
|
+
update
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** A simple black theme that works best on ligh backgrounds **/
|
|
2
|
+
.a9s-annotationlayer .a9s-outer,
|
|
3
|
+
div[data-theme="dark"] .a9s-annotationlayer .a9s-outer {
|
|
4
|
+
display: none;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.a9s-annotationlayer .a9s-inner,
|
|
8
|
+
div[data-theme="dark"] .a9s-annotationlayer .a9s-inner {
|
|
9
|
+
fill: rgba(0, 0, 0, 0.12);
|
|
10
|
+
stroke: #000;
|
|
11
|
+
stroke-width: 1px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
rect.a9s-corner-handle,
|
|
15
|
+
div[data-theme="dark"] rect.a9s-corner-handle {
|
|
16
|
+
fill: #000;
|
|
17
|
+
rx: 2px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
rect.a9s-close-polygon-handle,
|
|
21
|
+
div[data-theme="dark"] rect.a9s-close-polygon-handle {
|
|
22
|
+
fill: #000;
|
|
23
|
+
rx: 1px;
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './smart';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** A simple white theme that works best on dark backgrounds **/
|
|
2
|
+
.a9s-annotationlayer .a9s-outer,
|
|
3
|
+
div[data-theme="light"] .a9s-annotationlayer .a9s-outer {
|
|
4
|
+
display: block;
|
|
5
|
+
stroke: rgba(0, 0, 0, 0.25);
|
|
6
|
+
stroke-width: 3.5px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.a9s-annotationlayer .a9s-inner,
|
|
10
|
+
div[data-theme="light"] .a9s-annotationlayer .a9s-inner {
|
|
11
|
+
fill: rgba(255, 255, 255, 0.15);
|
|
12
|
+
stroke: #fff;
|
|
13
|
+
stroke-width: 1.5px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
rect.a9s-corner-handle,
|
|
17
|
+
div[data-theme="light"] rect.a9s-corner-handle {
|
|
18
|
+
fill: #fff;
|
|
19
|
+
rx: 1px;
|
|
20
|
+
stroke: rgba(0, 0, 0, 0.45);
|
|
21
|
+
stroke-width: 1px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
rect.a9s-close-polygon-handle,
|
|
25
|
+
div[data-theme="light"] rect.a9s-close-polygon-handle {
|
|
26
|
+
fill: #fff;
|
|
27
|
+
rx: 1px;
|
|
28
|
+
stroke: rgba(0, 0, 0, 0.45);
|
|
29
|
+
stroke-width: 1px;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './setTheme';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
|
|
2
|
+
|
|
3
|
+
let canvas: HTMLCanvasElement;
|
|
4
|
+
|
|
5
|
+
let context: CanvasRenderingContext2D;
|
|
6
|
+
|
|
7
|
+
if (imageOrCanvas.nodeName === 'CANVAS') {
|
|
8
|
+
canvas = imageOrCanvas as HTMLCanvasElement;
|
|
9
|
+
context = canvas.getContext('2d', { willReadFrequently: true });
|
|
10
|
+
} else {
|
|
11
|
+
const img = imageOrCanvas as HTMLImageElement;
|
|
12
|
+
// Copy image to in-memory canvas for processing
|
|
13
|
+
canvas = document.createElement('canvas');
|
|
14
|
+
canvas.width = img.width;
|
|
15
|
+
canvas.height = img.height;
|
|
16
|
+
|
|
17
|
+
context = canvas.getContext('2d', { willReadFrequently: true });
|
|
18
|
+
context.drawImage(img, 0, 0, img.width, img.height);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let totalBrightness = 0;
|
|
22
|
+
|
|
23
|
+
// Sample a grid of points spaced 10% width/height apart (= 9 x 9 samples)
|
|
24
|
+
for (let i = 1; i < 10; i++) {
|
|
25
|
+
for (let j = 1; j < 10; j++) {
|
|
26
|
+
const x = Math.round(j * canvas.width / 10);
|
|
27
|
+
const y = Math.round(i * canvas.height / 10);
|
|
28
|
+
|
|
29
|
+
const pixelData = context.getImageData(x, y, 1, 1).data;
|
|
30
|
+
const brightness = (0.299 * pixelData[0] + 0.587 * pixelData[1] + 0.114 * pixelData[2]) / 255;
|
|
31
|
+
totalBrightness += brightness;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return totalBrightness / 81;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const setTheme = (imageOrCanvas: HTMLElement, container: HTMLElement) => {
|
|
39
|
+
const brightness = sampleBrightness(imageOrCanvas);
|
|
40
|
+
|
|
41
|
+
const theme = brightness > 0.6 ? 'dark' : 'light'
|
|
42
|
+
|
|
43
|
+
console.log(`[Annotorious] Image brightness: ${brightness.toFixed(1)}. Setting ${theme} theme.`);
|
|
44
|
+
|
|
45
|
+
container.setAttribute('data-theme', theme);
|
|
46
|
+
}
|