Skip to content

Commit 3f8fd3d

Browse files
committed
Replace image with canvas
1 parent 4314f9e commit 3f8fd3d

File tree

4 files changed

+53
-21
lines changed

4 files changed

+53
-21
lines changed

application/ui/src/features/annotator/annotations/annotation.component.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,24 @@
44
import type { Annotation as AnnotationType } from '../types';
55
import { AnnotationContext } from './annotation-context';
66
import { AnnotationShapeWithLabels } from './annotation-shape-with-labels.component';
7+
import { AnnotationShape } from './annotation-shape.component';
78
import { EditableAnnotation } from './editable-annotation.component';
89
import { SelectableAnnotation } from './selectable-annotation.component';
910

1011
interface AnnotationProps {
1112
annotation: AnnotationType;
13+
withLabels?: boolean;
1214
}
13-
export const Annotation = ({ annotation }: AnnotationProps) => {
15+
export const Annotation = ({ annotation, withLabels }: AnnotationProps) => {
1416
return (
1517
<AnnotationContext.Provider value={annotation}>
1618
<SelectableAnnotation>
1719
<EditableAnnotation>
18-
<AnnotationShapeWithLabels annotation={annotation} />
20+
{withLabels ? (
21+
<AnnotationShapeWithLabels annotation={annotation} />
22+
) : (
23+
<AnnotationShape annotation={annotation} />
24+
)}
1925
</EditableAnnotation>
2026
</SelectableAnnotation>
2127
</AnnotationContext.Provider>

application/ui/src/features/annotator/annotations/annotations.component.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright (C) 2025 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { MouseEvent } from 'react';
4+
import { CSSProperties, MouseEvent } from 'react';
55

66
import { isEmpty } from 'lodash-es';
7+
import { useAnnotationVisibility } from 'src/shared/annotator/annotation-visibility-provider.component';
78

89
import { useSelectedAnnotations } from '../../../shared/annotator/select-annotation-provider.component';
910
import type { Annotation as AnnotationType } from '../types';
@@ -20,6 +21,7 @@ type AnnotationsProps = {
2021

2122
export const Annotations = ({ annotations, width, height, isFocussed }: AnnotationsProps) => {
2223
const { setSelectedAnnotations } = useSelectedAnnotations();
24+
const { isVisible } = useAnnotationVisibility();
2325

2426
// If the user clicks on an empty spot on the canvas, we want to deselect
2527
// all annotations
@@ -36,19 +38,25 @@ export const Annotations = ({ annotations, width, height, isFocussed }: Annotati
3638
height={height}
3739
tabIndex={-1}
3840
onClick={handleBackgroundClick}
39-
style={{
40-
position: 'absolute',
41-
inset: 0,
42-
outline: 'none',
43-
overflow: 'visible',
44-
...DEFAULT_ANNOTATION_STYLES,
45-
}}
41+
style={
42+
{
43+
'--annotation-stroke': '1px solid var(--energy-blue)',
44+
'--annotation-fill': 'rgba(0, 199, 253, 0.2)',
45+
position: 'absolute',
46+
inset: 0,
47+
outline: 'none',
48+
overflow: 'visible',
49+
...DEFAULT_ANNOTATION_STYLES,
50+
} as CSSProperties
51+
}
4652
>
47-
{!isEmpty(annotations) && (
53+
{!isEmpty(annotations) && isVisible && (
4854
<MaskAnnotations annotations={annotations} width={width} height={height} isEnabled={isFocussed}>
49-
{annotations.map((annotation) => (
50-
<Annotation annotation={annotation} key={annotation.id} />
51-
))}
55+
<g aria-label={'annotation list'}>
56+
{annotations.map((annotation) => (
57+
<Annotation annotation={annotation} key={annotation.id} />
58+
))}
59+
</g>
5260
</MaskAnnotations>
5361
)}
5462
</svg>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.image {
2+
filter: brightness(var(--image-brightness)) saturate(var(--image-saturation)) contrast(var(--image-contrast));
3+
image-rendering: var(--pixel-view);
4+
}

application/ui/src/features/annotator/annotator-canvas.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
// Copyright (C) 2025 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { useCallback } from 'react';
5+
46
import { View } from '@geti/ui';
5-
import { useProjectIdentifier } from 'hooks/use-project-identifier.hook';
6-
import { API_BASE_URL } from 'src/api/client';
77
import type { DatasetItem } from 'src/constants/shared-types';
8+
import { useAnnotator } from 'src/shared/annotator/annotator-provider.component';
89

910
import { ZoomTransform } from '../../components/zoom/zoom-transform';
1011
import { useAnnotationActions } from '../../shared/annotator/annotation-actions-provider.component';
@@ -13,19 +14,32 @@ import { useSelectedAnnotations } from '../../shared/annotator/select-annotation
1314
import { Annotations } from './annotations/annotations.component';
1415
import { ToolManager } from './tools/tool-manager.component';
1516

16-
const getImageUrl = (projectId: string, itemId: string) => {
17-
return `${API_BASE_URL}/api/projects/${projectId}/dataset/items/${itemId}/binary`;
18-
};
17+
import styles from './annotator-canvas.module.scss';
1918

2019
type AnnotatorCanvasProps = {
2120
mediaItem: DatasetItem;
2221
};
2322

2423
export const AnnotatorCanvas = ({ mediaItem }: AnnotatorCanvasProps) => {
25-
const project_id = useProjectIdentifier();
2624
const { annotations } = useAnnotationActions();
2725
const { selectedAnnotations } = useSelectedAnnotations();
2826
const { isFocussed } = useAnnotationVisibility();
27+
const { image } = useAnnotator();
28+
29+
const drawImageOnCanvas = useCallback(
30+
(canvasRef: HTMLCanvasElement | null) => {
31+
if (!canvasRef) return;
32+
33+
canvasRef.width = image.width;
34+
canvasRef.height = image.height;
35+
36+
const ctx = canvasRef.getContext('2d');
37+
if (ctx) {
38+
ctx.putImageData(image, 0, 0);
39+
}
40+
},
41+
[image]
42+
);
2943

3044
// Order annotations by selection. Selected annotation should always be on top.
3145
const orderedAnnotations = [
@@ -38,7 +52,7 @@ export const AnnotatorCanvas = ({ mediaItem }: AnnotatorCanvasProps) => {
3852
return (
3953
<ZoomTransform target={size}>
4054
<View position={'relative'} width={'100%'} height={'100%'}>
41-
<img src={getImageUrl(project_id, String(mediaItem.id))} alt='Collected data' />
55+
<canvas aria-label='Captured frame' ref={drawImageOnCanvas} className={styles.image} />
4256

4357
<Annotations
4458
annotations={orderedAnnotations}

0 commit comments

Comments
 (0)