lost-sia 0.5.2 → 0.9.0
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/CHANGELOG.md +23 -0
- package/dist/index.css +2 -2
- package/dist/index.es.js +241 -67
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +241 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
## [0.9.0] - 2021-12-23
|
|
9
|
+
### Added
|
|
10
|
+
- Delete annotation in creation mode when hitting *Escape*-Key
|
|
11
|
+
- Show img description in ImgBar if available
|
|
12
|
+
- Max canvas size mode. Where canvas takes the maximum container size and is not
|
|
13
|
+
image oriented as before. Add prop *maxCanvas={true}* to canvas in order to enable.
|
|
14
|
+
### Changed
|
|
15
|
+
- Be able to deal with mixed color possible labels -> where a part of labels
|
|
16
|
+
will have a specified color and the other part has no provided color
|
|
17
|
+
|
|
18
|
+
## [0.8.0] - 2021-10-14
|
|
19
|
+
### Added
|
|
20
|
+
- Added lockedAnnos prop for Canvas in order to lock annos by id. Locked annos
|
|
21
|
+
can not be edited
|
|
22
|
+
|
|
23
|
+
## [0.7.0] - 2021-10-13
|
|
24
|
+
### Added
|
|
25
|
+
- Update annotations on **annos**-prob change
|
|
26
|
+
|
|
27
|
+
## [0.6.0] - 2021-09-28
|
|
28
|
+
### Added
|
|
29
|
+
- Edit mode for Polygons -> Edit polygons again that already have been created
|
|
30
|
+
|
|
8
31
|
## [0.5.2] - 2021-07-22
|
|
9
32
|
### Changed
|
|
10
33
|
- do not spam logs with toSia function
|
package/dist/index.css
CHANGED
package/dist/index.es.js
CHANGED
|
@@ -4,13 +4,13 @@ import _ from 'lodash';
|
|
|
4
4
|
|
|
5
5
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
6
6
|
|
|
7
|
-
function toSia(data, image, type) {
|
|
7
|
+
function toSia(data, image, type, imgOffset) {
|
|
8
8
|
switch (type) {
|
|
9
9
|
case 'bBox':
|
|
10
10
|
var w = image.width * data.w;
|
|
11
11
|
var h = image.height * data.h;
|
|
12
|
-
var x0 = image.width * data.x - w / 2.0;
|
|
13
|
-
var y0 = image.height * data.y - h / 2.0;
|
|
12
|
+
var x0 = imgOffset.x + image.width * data.x - w / 2.0;
|
|
13
|
+
var y0 = imgOffset.y + image.height * data.y - h / 2.0;
|
|
14
14
|
return [{
|
|
15
15
|
x: x0,
|
|
16
16
|
y: y0
|
|
@@ -26,15 +26,15 @@ function toSia(data, image, type) {
|
|
|
26
26
|
}];
|
|
27
27
|
case 'point':
|
|
28
28
|
return [{
|
|
29
|
-
x: image.width * data.x,
|
|
30
|
-
y: image.height * data.y
|
|
29
|
+
x: imgOffset.x + image.width * data.x,
|
|
30
|
+
y: imgOffset.y + image.height * data.y
|
|
31
31
|
}];
|
|
32
32
|
case 'line':
|
|
33
33
|
case 'polygon':
|
|
34
34
|
return data.map(function (e) {
|
|
35
35
|
return {
|
|
36
|
-
x: image.width * e.x,
|
|
37
|
-
y: image.height * e.y
|
|
36
|
+
x: imgOffset.x + image.width * e.x,
|
|
37
|
+
y: imgOffset.y + image.height * e.y
|
|
38
38
|
};
|
|
39
39
|
});
|
|
40
40
|
default:
|
|
@@ -46,17 +46,21 @@ function toSia(data, image, type) {
|
|
|
46
46
|
* Transform a sia annotation to backend format.
|
|
47
47
|
*
|
|
48
48
|
* @param {Array} data Annotation data
|
|
49
|
-
* @param {*}
|
|
49
|
+
* @param {*} svg Image object {width, height}
|
|
50
50
|
* @param {String} type Type of the annotation bBox, point, line, polygon
|
|
51
51
|
* @returns Annotation data in backend style (relative, centered)
|
|
52
52
|
*/
|
|
53
|
-
function toBackend(data,
|
|
53
|
+
function toBackend(data, svg, type) {
|
|
54
|
+
var imgOffset = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { x: 0, y: 0 };
|
|
55
|
+
|
|
56
|
+
var imgWidth = svg.width - 2 * imgOffset.x;
|
|
57
|
+
var imgHeight = svg.height - 2 * imgOffset.y;
|
|
54
58
|
switch (type) {
|
|
55
59
|
case 'bBox':
|
|
56
|
-
// const w =
|
|
57
|
-
// const h =
|
|
58
|
-
// const x0 =
|
|
59
|
-
// const y0 =
|
|
60
|
+
// const w = svg.width * data.w
|
|
61
|
+
// const h = svg.height * data.h
|
|
62
|
+
// const x0 = svg.width * data.x - w/2.0
|
|
63
|
+
// const y0 = svg.height * data.y - h/2.0
|
|
60
64
|
|
|
61
65
|
// console.error('GO On Here! w = max_x - min_x; h = max_y - min_y')
|
|
62
66
|
var xList = data.map(function (e) {
|
|
@@ -65,30 +69,30 @@ function toBackend(data, image, type) {
|
|
|
65
69
|
var yList = data.map(function (e) {
|
|
66
70
|
return e.y;
|
|
67
71
|
});
|
|
68
|
-
var minX = Math.min.apply(Math, _toConsumableArray(xList));
|
|
69
|
-
var maxX = Math.max.apply(Math, _toConsumableArray(xList));
|
|
70
|
-
var minY = Math.min.apply(Math, _toConsumableArray(yList));
|
|
71
|
-
var maxY = Math.max.apply(Math, _toConsumableArray(yList));
|
|
72
|
+
var minX = Math.min.apply(Math, _toConsumableArray(xList)) - imgOffset.x;
|
|
73
|
+
var maxX = Math.max.apply(Math, _toConsumableArray(xList)) - imgOffset.x;
|
|
74
|
+
var minY = Math.min.apply(Math, _toConsumableArray(yList)) - imgOffset.y;
|
|
75
|
+
var maxY = Math.max.apply(Math, _toConsumableArray(yList)) - imgOffset.y;
|
|
72
76
|
var w = maxX - minX;
|
|
73
77
|
var h = maxY - minY;
|
|
74
78
|
var x = minX + w / 2.0;
|
|
75
79
|
var y = minY + h / 2.0;
|
|
76
80
|
return {
|
|
77
|
-
x: x /
|
|
78
|
-
y: y /
|
|
79
|
-
w: w /
|
|
80
|
-
h: h /
|
|
81
|
+
x: x / imgWidth,
|
|
82
|
+
y: y / imgHeight,
|
|
83
|
+
w: w / imgWidth,
|
|
84
|
+
h: h / imgHeight };
|
|
81
85
|
case 'point':
|
|
82
86
|
return {
|
|
83
|
-
x: data[0].x /
|
|
84
|
-
y: data[0].y /
|
|
87
|
+
x: (data[0].x - imgOffset.x) / imgWidth,
|
|
88
|
+
y: (data[0].y - imgOffset.y) / imgHeight
|
|
85
89
|
};
|
|
86
90
|
case 'line':
|
|
87
91
|
case 'polygon':
|
|
88
92
|
return data.map(function (e) {
|
|
89
93
|
return {
|
|
90
|
-
x: e.x /
|
|
91
|
-
y: e.y /
|
|
94
|
+
x: (e.x - imgOffset.x) / imgWidth,
|
|
95
|
+
y: (e.y - imgOffset.y) / imgHeight
|
|
92
96
|
};
|
|
93
97
|
});
|
|
94
98
|
default:
|
|
@@ -2448,7 +2452,7 @@ var Annotation$1 = function (_Component) {
|
|
|
2448
2452
|
}, {
|
|
2449
2453
|
key: 'getColor',
|
|
2450
2454
|
value: function getColor$$1() {
|
|
2451
|
-
if (this.state.anno.labelIds.length > 0) {
|
|
2455
|
+
if (this.state.anno.labelIds && this.state.anno.labelIds.length > 0) {
|
|
2452
2456
|
return this.getLabel(this.state.anno.labelIds[0]).color;
|
|
2453
2457
|
} else {
|
|
2454
2458
|
return getDefaultColor();
|
|
@@ -3153,6 +3157,19 @@ var ImgBar = function (_Component) {
|
|
|
3153
3157
|
return null;
|
|
3154
3158
|
}
|
|
3155
3159
|
}
|
|
3160
|
+
}, {
|
|
3161
|
+
key: 'renderImgDescription',
|
|
3162
|
+
value: function renderImgDescription() {
|
|
3163
|
+
if (this.props.annos.image.description) {
|
|
3164
|
+
return React.createElement(
|
|
3165
|
+
Menu.Item,
|
|
3166
|
+
null,
|
|
3167
|
+
this.props.annos.image.description
|
|
3168
|
+
);
|
|
3169
|
+
} else {
|
|
3170
|
+
return null;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3156
3173
|
}, {
|
|
3157
3174
|
key: 'render',
|
|
3158
3175
|
value: function render() {
|
|
@@ -3160,7 +3177,7 @@ var ImgBar = function (_Component) {
|
|
|
3160
3177
|
|
|
3161
3178
|
if (!this.props.visible) return null;
|
|
3162
3179
|
if (!this.props.annos.image) return null;
|
|
3163
|
-
if (!this.props.annos.image.url) return null
|
|
3180
|
+
// if (!this.props.annos.image.url) return null
|
|
3164
3181
|
return React.createElement(
|
|
3165
3182
|
'div',
|
|
3166
3183
|
{ style: {
|
|
@@ -3177,10 +3194,11 @@ var ImgBar = function (_Component) {
|
|
|
3177
3194
|
React.createElement(
|
|
3178
3195
|
Menu,
|
|
3179
3196
|
{ inverted: true, style: { opacity: 0.9, justifyContent: 'center', alignItems: 'center' } },
|
|
3197
|
+
this.renderImgDescription(),
|
|
3180
3198
|
React.createElement(
|
|
3181
3199
|
Menu.Item,
|
|
3182
3200
|
null,
|
|
3183
|
-
|
|
3201
|
+
"ID: " + this.props.annos.image.id
|
|
3184
3202
|
),
|
|
3185
3203
|
React.createElement(
|
|
3186
3204
|
Menu.Item,
|
|
@@ -3403,7 +3421,36 @@ var _extends$8 = Object.assign || function (target) { for (var i = 1; i < argume
|
|
|
3403
3421
|
|
|
3404
3422
|
function _toConsumableArray$3(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
3405
3423
|
|
|
3406
|
-
function
|
|
3424
|
+
function _fixBackendAnnoElement(element) {
|
|
3425
|
+
return _extends$8({}, element, {
|
|
3426
|
+
id: element.id ? element.id : _.uniqueId('new'),
|
|
3427
|
+
annoTime: element.annoTime ? element.annoTime : 0.0,
|
|
3428
|
+
mode: element.mode ? element.mode : VIEW,
|
|
3429
|
+
status: element.status ? element.status : DATABASE,
|
|
3430
|
+
labelIds: element.labelIds ? element.labelIds : []
|
|
3431
|
+
});
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
function fixBackendAnnos(backendAnnos) {
|
|
3435
|
+
var annos = {
|
|
3436
|
+
bBoxes: [].concat(_toConsumableArray$3(backendAnnos.bBoxes.map(function (element) {
|
|
3437
|
+
return _fixBackendAnnoElement(element);
|
|
3438
|
+
}))),
|
|
3439
|
+
lines: [].concat(_toConsumableArray$3(backendAnnos.lines.map(function (element) {
|
|
3440
|
+
return _fixBackendAnnoElement(element);
|
|
3441
|
+
}))),
|
|
3442
|
+
polygons: [].concat(_toConsumableArray$3(backendAnnos.polygons.map(function (element) {
|
|
3443
|
+
return _fixBackendAnnoElement(element);
|
|
3444
|
+
}))),
|
|
3445
|
+
points: [].concat(_toConsumableArray$3(backendAnnos.points.map(function (element) {
|
|
3446
|
+
return _fixBackendAnnoElement(element);
|
|
3447
|
+
})))
|
|
3448
|
+
};
|
|
3449
|
+
console.log('fixBackendAnnos', annos);
|
|
3450
|
+
return annos;
|
|
3451
|
+
}
|
|
3452
|
+
|
|
3453
|
+
function backendAnnosToCanvas(backendAnnos, imgSize, imgOffset) {
|
|
3407
3454
|
var annos = [].concat(_toConsumableArray$3(backendAnnos.bBoxes.map(function (element) {
|
|
3408
3455
|
return _extends$8({}, element, { type: 'bBox',
|
|
3409
3456
|
mode: element.mode ? element.mode : VIEW,
|
|
@@ -3424,7 +3471,7 @@ function backendAnnosToCanvas(backendAnnos, imgSize) {
|
|
|
3424
3471
|
})));
|
|
3425
3472
|
annos = annos.map(function (el) {
|
|
3426
3473
|
return _extends$8({}, el, {
|
|
3427
|
-
data: toSia(el.data, imgSize, el.type) });
|
|
3474
|
+
data: toSia(el.data, imgSize, el.type, imgOffset) });
|
|
3428
3475
|
});
|
|
3429
3476
|
// this.setState({annos: [...annos]})
|
|
3430
3477
|
return annos;
|
|
@@ -3432,6 +3479,7 @@ function backendAnnosToCanvas(backendAnnos, imgSize) {
|
|
|
3432
3479
|
|
|
3433
3480
|
function canvasToBackendAnnos(annos, imgSize) {
|
|
3434
3481
|
var forBackendPost = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
3482
|
+
var imgOffset = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { x: 0, y: 0 };
|
|
3435
3483
|
|
|
3436
3484
|
var myAnnos = annos;
|
|
3437
3485
|
var bAnnos = myAnnos.map(function (el) {
|
|
@@ -3447,7 +3495,7 @@ function canvasToBackendAnnos(annos, imgSize) {
|
|
|
3447
3495
|
return _extends$8({}, el, {
|
|
3448
3496
|
id: annoId,
|
|
3449
3497
|
mode: VIEW,
|
|
3450
|
-
data: toBackend(el.data, imgSize, el.type)
|
|
3498
|
+
data: toBackend(el.data, imgSize, el.type, imgOffset)
|
|
3451
3499
|
});
|
|
3452
3500
|
});
|
|
3453
3501
|
|
|
@@ -3486,6 +3534,8 @@ var CAM_MOVE_RIGHT = 'camMoveRight';
|
|
|
3486
3534
|
var CAM_MOVE_STOP = 'camMoveStop';
|
|
3487
3535
|
var COPY_ANNOTATION = 'copyAnnotation';
|
|
3488
3536
|
var PASTE_ANNOTATION = 'pasteAnnotation';
|
|
3537
|
+
var RECREATE_ANNO = 'recreateAnnotation';
|
|
3538
|
+
var DELETE_ANNO_IN_CREATION = 'deleteAnnoInCreation';
|
|
3489
3539
|
|
|
3490
3540
|
var KeyMapper = function () {
|
|
3491
3541
|
function KeyMapper() {
|
|
@@ -3539,6 +3589,9 @@ var KeyMapper = function () {
|
|
|
3539
3589
|
case 'd':
|
|
3540
3590
|
this.triggerKeyAction(CAM_MOVE_RIGHT);
|
|
3541
3591
|
break;
|
|
3592
|
+
case 'e':
|
|
3593
|
+
this.triggerKeyAction(RECREATE_ANNO);
|
|
3594
|
+
break;
|
|
3542
3595
|
case 'c':
|
|
3543
3596
|
if (this.controlDown) {
|
|
3544
3597
|
this.triggerKeyAction(COPY_ANNOTATION);
|
|
@@ -3549,6 +3602,9 @@ var KeyMapper = function () {
|
|
|
3549
3602
|
this.triggerKeyAction(PASTE_ANNOTATION);
|
|
3550
3603
|
}
|
|
3551
3604
|
break;
|
|
3605
|
+
case 'Escape':
|
|
3606
|
+
this.triggerKeyAction(DELETE_ANNO_IN_CREATION);
|
|
3607
|
+
break;
|
|
3552
3608
|
default:
|
|
3553
3609
|
break;
|
|
3554
3610
|
}
|
|
@@ -3702,7 +3758,7 @@ function getZoomTranslation(w0, svg, s1) {
|
|
|
3702
3758
|
return translation;
|
|
3703
3759
|
}
|
|
3704
3760
|
|
|
3705
|
-
var css$1 = ".SIA_sia-fullscreen__1P3FS {\n position: fixed;\n top: 0;\n left: 0;\n z-index:
|
|
3761
|
+
var css$1 = ".SIA_sia-fullscreen__1P3FS {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 9999;\n width: 100%;\n height: 100%;\n background-color: #FFFF; }\n";
|
|
3706
3762
|
styleInject(css$1);
|
|
3707
3763
|
|
|
3708
3764
|
var _extends$9 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
@@ -3727,17 +3783,19 @@ function _inherits$e(subClass, superClass) { if (typeof superClass !== "function
|
|
|
3727
3783
|
* {
|
|
3728
3784
|
* image : {
|
|
3729
3785
|
* id: int,
|
|
3730
|
-
* url: string,
|
|
3731
3786
|
* number: int,
|
|
3732
3787
|
* amount: int,
|
|
3733
3788
|
* isFirst: bool,
|
|
3734
|
-
* isLast: bool
|
|
3789
|
+
* isLast: bool,
|
|
3790
|
+
* description: string, // -> optional
|
|
3735
3791
|
* },
|
|
3736
3792
|
* annotations: {
|
|
3737
3793
|
* bBoxes: [{
|
|
3738
|
-
* id: int,
|
|
3739
|
-
*
|
|
3740
|
-
*
|
|
3794
|
+
* id: int, // -> Not required if status === annoStatus.NEW
|
|
3795
|
+
* data: {},
|
|
3796
|
+
* labelIds: list of int, // -> optional
|
|
3797
|
+
* status: see annoStatus, // -> optional
|
|
3798
|
+
* annoTime: float, // -> optional
|
|
3741
3799
|
* },...],
|
|
3742
3800
|
* points: []
|
|
3743
3801
|
* lines: []
|
|
@@ -3791,10 +3849,13 @@ function _inherits$e(subClass, superClass) { if (typeof superClass !== "function
|
|
|
3791
3849
|
* {left:int, top:int, right:int, bottom:int} values in pixels.
|
|
3792
3850
|
* @param {bool} centerCanvasInContainer - Center the canvas in the
|
|
3793
3851
|
* middle of the container.
|
|
3852
|
+
* @param {bool} maxCanvas - Maximize Canvas Size. Do not fit canvas to image size
|
|
3794
3853
|
* @param {str or int} defaultLabel (optional) - Name or ID of the default label that is used
|
|
3795
3854
|
* when no label was selected by the annotator. If not set "no label" will be used.
|
|
3796
3855
|
* If ID is used, it needs to be one of the possible label ids.
|
|
3797
3856
|
* @param {bool} blocked Block canvas view with loading dimmer.
|
|
3857
|
+
* @param {bool} lockedAnnos A list of AnnoIds of annos that should only be displayed.
|
|
3858
|
+
* Such annos can not be edited in any way.
|
|
3798
3859
|
* @event onSVGUpdate - Fires when the svg in canvas changed.
|
|
3799
3860
|
* args: {width: int, height: int, scale: float, translateX: float,
|
|
3800
3861
|
* translateY:float}
|
|
@@ -3832,6 +3893,10 @@ var Canvas = function (_Component) {
|
|
|
3832
3893
|
width: undefined,
|
|
3833
3894
|
height: undefined
|
|
3834
3895
|
},
|
|
3896
|
+
imageOffset: {
|
|
3897
|
+
x: 0,
|
|
3898
|
+
y: 0
|
|
3899
|
+
},
|
|
3835
3900
|
annos: [],
|
|
3836
3901
|
mode: VIEW,
|
|
3837
3902
|
// selectedAnnoId: {id:undefined},
|
|
@@ -3886,6 +3951,9 @@ var Canvas = function (_Component) {
|
|
|
3886
3951
|
imgLoadTimestamp: performance.now()
|
|
3887
3952
|
// isJunk: this.props.annos.image.isJunk
|
|
3888
3953
|
});
|
|
3954
|
+
if (this.state.imageData) {
|
|
3955
|
+
this.updateCanvasView(fixBackendAnnos(this.props.annos.annotations));
|
|
3956
|
+
}
|
|
3889
3957
|
// this.setState({
|
|
3890
3958
|
// imageLoaded: false,
|
|
3891
3959
|
// // imageData: undefined
|
|
@@ -3932,7 +4000,7 @@ var Canvas = function (_Component) {
|
|
|
3932
4000
|
// Selected annotation should be on top
|
|
3933
4001
|
this.putSelectedOnTop(prevState);
|
|
3934
4002
|
if (prevState.imgLoadCount !== this.state.imgLoadCount) {
|
|
3935
|
-
this.updateCanvasView(this.props.annos.annotations);
|
|
4003
|
+
this.updateCanvasView(fixBackendAnnos(this.props.annos.annotations));
|
|
3936
4004
|
this.setImageLabels(this.props.annos.image.labelIds);
|
|
3937
4005
|
this.setState({
|
|
3938
4006
|
performedImageInit: true
|
|
@@ -3941,7 +4009,8 @@ var Canvas = function (_Component) {
|
|
|
3941
4009
|
if (prevProps.layoutUpdate !== this.props.layoutUpdate) {
|
|
3942
4010
|
this.selectAnnotation(undefined);
|
|
3943
4011
|
// this.updateCanvasView(this.getAnnoBackendFormat())
|
|
3944
|
-
this.
|
|
4012
|
+
// const {imageOffset} = this.updateImageSize()
|
|
4013
|
+
this.updateCanvasView(canvasToBackendAnnos(this.state.annos, this.state.svg, false, this.state.imageOffset));
|
|
3945
4014
|
}
|
|
3946
4015
|
}
|
|
3947
4016
|
}
|
|
@@ -4065,14 +4134,10 @@ var Canvas = function (_Component) {
|
|
|
4065
4134
|
this.editAnnoLabel(myAnno);
|
|
4066
4135
|
break;
|
|
4067
4136
|
case DELETE_ANNO:
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
} else {
|
|
4073
|
-
this.onAnnoPerformedAction(anno, ANNO_DELETED);
|
|
4074
|
-
}
|
|
4075
|
-
}
|
|
4137
|
+
this.deleteAnnotation(anno);
|
|
4138
|
+
break;
|
|
4139
|
+
case DELETE_ANNO_IN_CREATION:
|
|
4140
|
+
this.deleteAnnoInCreationMode(anno);
|
|
4076
4141
|
break;
|
|
4077
4142
|
case ENTER_ANNO_ADD_MODE:
|
|
4078
4143
|
if (anno) {
|
|
@@ -4117,6 +4182,10 @@ var Canvas = function (_Component) {
|
|
|
4117
4182
|
case PASTE_ANNOTATION:
|
|
4118
4183
|
this.pasteAnnotation(0);
|
|
4119
4184
|
break;
|
|
4185
|
+
case RECREATE_ANNO:
|
|
4186
|
+
// recreate selected annotation using the anno id
|
|
4187
|
+
if (this.state.selectedAnnoId) this.recreateAnnotation(this.state.selectedAnnoId);
|
|
4188
|
+
break;
|
|
4120
4189
|
default:
|
|
4121
4190
|
console.warn('Unknown key action', action);
|
|
4122
4191
|
}
|
|
@@ -4398,11 +4467,13 @@ var Canvas = function (_Component) {
|
|
|
4398
4467
|
if (!this.props.possibleLabels) return;
|
|
4399
4468
|
if (this.props.possibleLabels.length <= 0) return;
|
|
4400
4469
|
var lbls = this.props.possibleLabels;
|
|
4401
|
-
|
|
4402
|
-
|
|
4470
|
+
lbls = lbls.map(function (e) {
|
|
4471
|
+
if (!('color' in e)) {
|
|
4403
4472
|
return _extends$9({}, e, { color: getColor(e.id) });
|
|
4404
|
-
}
|
|
4405
|
-
|
|
4473
|
+
} else {
|
|
4474
|
+
return _extends$9({}, e);
|
|
4475
|
+
}
|
|
4476
|
+
});
|
|
4406
4477
|
this.setState({
|
|
4407
4478
|
possibleLabels: [].concat(_toConsumableArray$4(lbls))
|
|
4408
4479
|
});
|
|
@@ -4481,6 +4552,29 @@ var Canvas = function (_Component) {
|
|
|
4481
4552
|
this.setCanvasState(cState.entry.annotations, cState.entry.imgLabelIds, cState.entry.selectedAnnoId, cState.entry.showSingleAnno);
|
|
4482
4553
|
}
|
|
4483
4554
|
}
|
|
4555
|
+
}, {
|
|
4556
|
+
key: 'deleteAnnotation',
|
|
4557
|
+
value: function deleteAnnotation(anno) {
|
|
4558
|
+
if (anno) {
|
|
4559
|
+
if (anno.mode === CREATE) {
|
|
4560
|
+
var ar = this.findAnnoRef(this.state.selectedAnnoId);
|
|
4561
|
+
if (ar !== undefined) ar.current.myAnno.current.removeLastNode();
|
|
4562
|
+
} else {
|
|
4563
|
+
this.onAnnoPerformedAction(anno, ANNO_DELETED);
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
}, {
|
|
4568
|
+
key: 'deleteAnnoInCreationMode',
|
|
4569
|
+
value: function deleteAnnoInCreationMode(anno) {
|
|
4570
|
+
if (anno) {
|
|
4571
|
+
if (anno.mode === CREATE) {
|
|
4572
|
+
// const ar = this.findAnnoRef(this.state.selectedAnnoId)
|
|
4573
|
+
// if (ar !== undefined) ar.current.myAnno.current.removeLastNode()
|
|
4574
|
+
this.onAnnoPerformedAction(anno, ANNO_DELETED);
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4484
4578
|
}, {
|
|
4485
4579
|
key: 'deleteAllAnnos',
|
|
4486
4580
|
value: function deleteAllAnnos() {
|
|
@@ -4514,9 +4608,27 @@ var Canvas = function (_Component) {
|
|
|
4514
4608
|
this.selectAnnotation(selectedAnnoId);
|
|
4515
4609
|
this.setState({ showSingleAnno: showSingleAnno });
|
|
4516
4610
|
}
|
|
4611
|
+
}, {
|
|
4612
|
+
key: 'isLocked',
|
|
4613
|
+
value: function isLocked(annoId) {
|
|
4614
|
+
if (this.props.lockedAnnos) {
|
|
4615
|
+
if (this.props.lockedAnnos.includes(annoId)) {
|
|
4616
|
+
return true;
|
|
4617
|
+
}
|
|
4618
|
+
}
|
|
4619
|
+
return false;
|
|
4620
|
+
}
|
|
4517
4621
|
}, {
|
|
4518
4622
|
key: 'selectAnnotation',
|
|
4519
4623
|
value: function selectAnnotation(annoId) {
|
|
4624
|
+
if (this.isLocked(annoId)) {
|
|
4625
|
+
this.handleNotification({
|
|
4626
|
+
title: "Annotation locked",
|
|
4627
|
+
message: 'Annotation with id ' + annoId + ' is locked and can not be edited',
|
|
4628
|
+
type: WARNING
|
|
4629
|
+
});
|
|
4630
|
+
return;
|
|
4631
|
+
}
|
|
4520
4632
|
if (annoId) {
|
|
4521
4633
|
var anno = this.findAnno(annoId);
|
|
4522
4634
|
this.setState({
|
|
@@ -4555,7 +4667,7 @@ var Canvas = function (_Component) {
|
|
|
4555
4667
|
|
|
4556
4668
|
if (this.state.annos.length > 0) {
|
|
4557
4669
|
var myAnnos = this.state.annos.filter(function (e) {
|
|
4558
|
-
return e.status !== DELETED$1;
|
|
4670
|
+
return e.status !== DELETED$1 && !_this2.isLocked(e.id);
|
|
4559
4671
|
});
|
|
4560
4672
|
if (myAnnos.length > 0) {
|
|
4561
4673
|
if (!this.state.selectedAnnoId) {
|
|
@@ -4581,7 +4693,7 @@ var Canvas = function (_Component) {
|
|
|
4581
4693
|
|
|
4582
4694
|
var myAnnos = annos ? annos : this.state.annos;
|
|
4583
4695
|
// const backendFormat = this.getAnnoBackendFormat(removeFrontedIds, myAnnos)
|
|
4584
|
-
var backendFormat = canvasToBackendAnnos(myAnnos, this.state.svg, removeFrontedIds);
|
|
4696
|
+
var backendFormat = canvasToBackendAnnos(myAnnos, this.state.svg, removeFrontedIds, this.state.imageOffset);
|
|
4585
4697
|
var finalData = {
|
|
4586
4698
|
imgId: this.props.annos.image.id,
|
|
4587
4699
|
imgLabelIds: this.state.imgLabelIds,
|
|
@@ -4730,6 +4842,56 @@ var Canvas = function (_Component) {
|
|
|
4730
4842
|
}
|
|
4731
4843
|
}
|
|
4732
4844
|
}
|
|
4845
|
+
|
|
4846
|
+
/**
|
|
4847
|
+
* recreate an existing annotation in case the creation process was not finished
|
|
4848
|
+
* @param {string} id of annotation
|
|
4849
|
+
*/
|
|
4850
|
+
|
|
4851
|
+
}, {
|
|
4852
|
+
key: 'recreateAnnotation',
|
|
4853
|
+
value: function recreateAnnotation(annoID) {
|
|
4854
|
+
|
|
4855
|
+
var annos = this.state.annos;
|
|
4856
|
+
|
|
4857
|
+
// search for id of selected anno in all annos (should normally be last item in list, but to be sure)
|
|
4858
|
+
var annoIndex = void 0;
|
|
4859
|
+
var anno = void 0;
|
|
4860
|
+
|
|
4861
|
+
for (var k in annos) {
|
|
4862
|
+
if (annos[k].id == annoID) {
|
|
4863
|
+
annoIndex = k;
|
|
4864
|
+
anno = annos[k];
|
|
4865
|
+
break;
|
|
4866
|
+
}
|
|
4867
|
+
} // editing is only allowed on line and polygon
|
|
4868
|
+
if (!['line', 'polygon'].includes(anno.type)) return console.log("Cant recreate annotation: Type " + anno.type + " is forbidden");
|
|
4869
|
+
|
|
4870
|
+
// remove the old annotation
|
|
4871
|
+
this.state.annos.splice(annoIndex, 1);
|
|
4872
|
+
|
|
4873
|
+
// create a new annotation based on the datapoints of the old annotation
|
|
4874
|
+
var newAnno = {
|
|
4875
|
+
id: anno.id,
|
|
4876
|
+
type: anno.type,
|
|
4877
|
+
data: anno.data,
|
|
4878
|
+
mode: CREATE,
|
|
4879
|
+
status: anno.status == 'database' ? CHANGED : NEW,
|
|
4880
|
+
labelIds: anno.labelIds,
|
|
4881
|
+
selectedNode: anno.data.length - 1,
|
|
4882
|
+
annoTime: anno.annoTime
|
|
4883
|
+
};
|
|
4884
|
+
|
|
4885
|
+
newAnno = this.startAnnotimeMeasure(newAnno);
|
|
4886
|
+
this.setState({
|
|
4887
|
+
annos: [].concat(_toConsumableArray$4(this.state.annos), [newAnno]),
|
|
4888
|
+
selectedAnnoId: newAnno.id,
|
|
4889
|
+
showSingleAnno: newAnno.id,
|
|
4890
|
+
annoToolBarVisible: false
|
|
4891
|
+
});
|
|
4892
|
+
|
|
4893
|
+
console.log("Annotation recreated");
|
|
4894
|
+
}
|
|
4733
4895
|
}, {
|
|
4734
4896
|
key: 'putSelectedOnTop',
|
|
4735
4897
|
value: function putSelectedOnTop(prevState) {
|
|
@@ -4882,28 +5044,40 @@ var Canvas = function (_Component) {
|
|
|
4882
5044
|
imgWidth = maxImgHeight * ratio;
|
|
4883
5045
|
imgHeight = maxImgHeight;
|
|
4884
5046
|
}
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
5047
|
+
var svg;
|
|
5048
|
+
var imgOffset = { x: 0, y: 0 };
|
|
5049
|
+
if (this.props.maxCanvas) {
|
|
5050
|
+
imgOffset.x = (maxImgWidth - imgWidth) / 2;
|
|
5051
|
+
imgOffset.y = (maxImgHeight - imgHeight) / 2;
|
|
5052
|
+
console.log('imgOffset: ', imgOffset);
|
|
5053
|
+
svg = _extends$9({}, this.state.svg, { width: maxImgWidth, height: maxImgHeight,
|
|
5054
|
+
left: canvasLeft, top: canvasTop
|
|
5055
|
+
});
|
|
5056
|
+
} else {
|
|
5057
|
+
if (this.props.centerCanvasInContainer) {
|
|
5058
|
+
var resSpaceX = maxImgWidth - imgWidth;
|
|
5059
|
+
if (resSpaceX > 2) {
|
|
5060
|
+
canvasLeft = canvasLeft + resSpaceX / 2;
|
|
5061
|
+
}
|
|
5062
|
+
var resSpaceY = maxImgHeight - imgHeight;
|
|
5063
|
+
if (resSpaceY > 2) {
|
|
5064
|
+
canvasTop = canvasTop + resSpaceY / 2;
|
|
5065
|
+
}
|
|
4893
5066
|
}
|
|
5067
|
+
svg = _extends$9({}, this.state.svg, { width: imgWidth, height: imgHeight,
|
|
5068
|
+
left: canvasLeft, top: canvasTop
|
|
5069
|
+
});
|
|
4894
5070
|
}
|
|
4895
|
-
var svg = _extends$9({}, this.state.svg, { width: imgWidth, height: imgHeight,
|
|
4896
|
-
left: canvasLeft, top: canvasTop
|
|
4897
|
-
});
|
|
4898
5071
|
this.setState({
|
|
4899
5072
|
svg: svg,
|
|
4900
5073
|
image: {
|
|
4901
5074
|
width: this.img.current.naturalWidth,
|
|
4902
5075
|
height: this.img.current.naturalHeight
|
|
4903
|
-
}
|
|
5076
|
+
},
|
|
5077
|
+
imageOffset: imgOffset
|
|
4904
5078
|
});
|
|
4905
5079
|
this.svgUpdate(svg);
|
|
4906
|
-
return { imgWidth: imgWidth, imgHeight: imgHeight };
|
|
5080
|
+
return { imgWidth: imgWidth, imgHeight: imgHeight, imgOffset: imgOffset };
|
|
4907
5081
|
}
|
|
4908
5082
|
}, {
|
|
4909
5083
|
key: 'svgUpdate',
|
|
@@ -4928,7 +5102,7 @@ var Canvas = function (_Component) {
|
|
|
4928
5102
|
//for svg should be calculated
|
|
4929
5103
|
if (annotations) {
|
|
4930
5104
|
var imgSize = this.updateImageSize();
|
|
4931
|
-
this.setState({ annos: [].concat(_toConsumableArray$4(backendAnnosToCanvas(annotations, { width: imgSize.imgWidth, height: imgSize.imgHeight }))) });
|
|
5105
|
+
this.setState({ annos: [].concat(_toConsumableArray$4(backendAnnosToCanvas(annotations, { width: imgSize.imgWidth, height: imgSize.imgHeight }, imgSize.imgOffset))) });
|
|
4932
5106
|
}
|
|
4933
5107
|
}
|
|
4934
5108
|
}, {
|