image-js 0.35.2 → 0.35.4
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/index.d.ts +3 -10
- package/lib/browser/environment.js +0 -6
- package/lib/browser/worker/extend.js +0 -3
- package/lib/browser/worker/process/background.js +0 -12
- package/lib/browser/worker/worker.js +0 -17
- package/lib/image/Image.js +18 -51
- package/lib/image/compute/colorHistogram.js +0 -8
- package/lib/image/compute/countAlphaPixels.js +0 -3
- package/lib/image/compute/extendedPoints.js +2 -7
- package/lib/image/compute/histogram.js +6 -25
- package/lib/image/compute/localMaxima.js +2 -10
- package/lib/image/compute/max.js +0 -5
- package/lib/image/compute/mean.js +0 -4
- package/lib/image/compute/median.js +0 -4
- package/lib/image/compute/min.js +0 -5
- package/lib/image/compute/minimalBoundingRectangle.js +5 -18
- package/lib/image/compute/moment.js +0 -3
- package/lib/image/compute/monotoneChainConvexHull.js +0 -3
- package/lib/image/compute/points.js +0 -3
- package/lib/image/compute/relativePosition.js +2 -8
- package/lib/image/compute/sum.js +0 -5
- package/lib/image/core/bitMethods.js +0 -11
- package/lib/image/core/checkProcessable.js +0 -13
- package/lib/image/core/environment.js +0 -8
- package/lib/image/core/export.js +0 -38
- package/lib/image/core/extend.js +0 -13
- package/lib/image/core/getRGBAData.js +0 -15
- package/lib/image/core/kind.js +4 -28
- package/lib/image/core/kindNames.js +1 -0
- package/lib/image/core/load.js +1 -53
- package/lib/image/core/mediaTypes.js +0 -2
- package/lib/image/core/valueMethods.js +0 -13
- package/lib/image/extend.js +7 -83
- package/lib/image/filter/abs.js +0 -3
- package/lib/image/filter/add.js +2 -8
- package/lib/image/filter/background.js +0 -9
- package/lib/image/filter/blurFilter.js +0 -6
- package/lib/image/filter/divide.js +0 -8
- package/lib/image/filter/flipX.js +0 -5
- package/lib/image/filter/flipY.js +0 -4
- package/lib/image/filter/gaussianFilter.js +0 -5
- package/lib/image/filter/gradientFilter.js +0 -11
- package/lib/image/filter/hypotenuse.js +0 -13
- package/lib/image/filter/invert.js +0 -9
- package/lib/image/filter/level.js +1 -19
- package/lib/image/filter/medianFilter.js +0 -15
- package/lib/image/filter/multiply.js +0 -10
- package/lib/image/filter/scharrFilter.js +0 -4
- package/lib/image/filter/sobelFilter.js +0 -4
- package/lib/image/filter/subtract.js +0 -8
- package/lib/image/filter/subtractImage.js +0 -10
- package/lib/image/internal/checks.js +1 -9
- package/lib/image/internal/clamp.js +0 -1
- package/lib/image/internal/copy.js +0 -2
- package/lib/image/internal/copyAlphaChannel.js +0 -1
- package/lib/image/internal/getImageParameters.js +0 -1
- package/lib/image/internal/getOutputImage.js +1 -13
- package/lib/image/model/model.js +1 -1
- package/lib/image/morphology/blackHat.js +0 -5
- package/lib/image/morphology/close.js +0 -5
- package/lib/image/morphology/dilate.js +0 -40
- package/lib/image/morphology/erode.js +0 -40
- package/lib/image/morphology/morphologicalGradient.js +0 -5
- package/lib/image/morphology/open.js +0 -5
- package/lib/image/morphology/topHat.js +0 -5
- package/lib/image/operator/cannyEdge.js +0 -3
- package/lib/image/operator/convolution.js +9 -34
- package/lib/image/operator/convolutionSeparable.js +0 -10
- package/lib/image/operator/extract.js +4 -13
- package/lib/image/operator/floodFill.js +2 -15
- package/lib/image/operator/getSeparatedKernel.js +0 -2
- package/lib/image/operator/paintLabels.js +2 -13
- package/lib/image/operator/paintMasks.js +2 -12
- package/lib/image/operator/paintPoints.js +0 -9
- package/lib/image/operator/paintPolygon.js +0 -14
- package/lib/image/operator/paintPolygons.js +0 -4
- package/lib/image/operator/paintPolyline.js +0 -7
- package/lib/image/operator/paintPolylines.js +0 -4
- package/lib/image/roi/Roi.js +27 -208
- package/lib/image/roi/RoiLayer.js +1 -22
- package/lib/image/roi/RoiMap.js +5 -38
- package/lib/image/roi/creator/fromMask.js +4 -22
- package/lib/image/roi/creator/fromMaskConnectedComponentLabelingAlgorithm.js +2 -20
- package/lib/image/roi/creator/fromMaxima.js +10 -43
- package/lib/image/roi/creator/fromPoints.js +2 -10
- package/lib/image/roi/creator/fromWaterShed.js +6 -17
- package/lib/image/roi/feretDiameters.js +9 -21
- package/lib/image/roi/manager.js +30 -119
- package/lib/image/roi/util/commonBorderLength.js +5 -16
- package/lib/image/roi/util/mergeRoi.js +2 -21
- package/lib/image/transform/cmyk.js +0 -9
- package/lib/image/transform/colorDepth.js +0 -12
- package/lib/image/transform/crop.js +0 -20
- package/lib/image/transform/cropAlpha.js +0 -11
- package/lib/image/transform/grey.js +0 -17
- package/lib/image/transform/greyAlgorithms.js +1 -24
- package/lib/image/transform/hsl.js +0 -16
- package/lib/image/transform/hsv.js +0 -15
- package/lib/image/transform/insert.js +0 -6
- package/lib/image/transform/mask/huang.js +3 -18
- package/lib/image/transform/mask/intermodes.js +3 -14
- package/lib/image/transform/mask/isodata.js +0 -14
- package/lib/image/transform/mask/li.js +12 -42
- package/lib/image/transform/mask/mask.js +1 -13
- package/lib/image/transform/mask/maxEntropy.js +8 -25
- package/lib/image/transform/mask/mean.js +1 -3
- package/lib/image/transform/mask/minError.js +10 -21
- package/lib/image/transform/mask/minimum.js +0 -20
- package/lib/image/transform/mask/moments.js +4 -17
- package/lib/image/transform/mask/otsu.js +1 -7
- package/lib/image/transform/mask/percentile.js +0 -8
- package/lib/image/transform/mask/renyiEntropy.js +8 -34
- package/lib/image/transform/mask/shanbhag.js +8 -25
- package/lib/image/transform/mask/thresholdAlgorithms.js +1 -17
- package/lib/image/transform/mask/triangle.js +13 -29
- package/lib/image/transform/mask/yen.js +2 -14
- package/lib/image/transform/pad.js +0 -20
- package/lib/image/transform/resize/nearestNeighbor.js +0 -6
- package/lib/image/transform/resize/resize.js +0 -16
- package/lib/image/transform/rgba.js +0 -9
- package/lib/image/transform/rgba8.js +0 -3
- package/lib/image/transform/rotate.js +0 -29
- package/lib/image/transform/rotateFree.js +0 -31
- package/lib/image/transform/warping.js +2 -35
- package/lib/image/utility/combineChannels.js +0 -11
- package/lib/image/utility/getBestMatch.js +2 -13
- package/lib/image/utility/getChannel.js +0 -10
- package/lib/image/utility/getClosestCommonParent.js +6 -23
- package/lib/image/utility/getColumn.js +0 -4
- package/lib/image/utility/getIntersection.js +2 -18
- package/lib/image/utility/getMatrix.js +0 -7
- package/lib/image/utility/getPixelsArray.js +0 -5
- package/lib/image/utility/getPixelsGrid.js +0 -11
- package/lib/image/utility/getRow.js +0 -4
- package/lib/image/utility/getSimilarity.js +3 -17
- package/lib/image/utility/getThreshold.js +0 -4
- package/lib/image/utility/setBorder.js +0 -16
- package/lib/image/utility/setChannel.js +0 -6
- package/lib/image/utility/setMatrix.js +3 -6
- package/lib/image/utility/split.js +2 -15
- package/lib/index.js +0 -12
- package/lib/kernel/kernel.js +0 -3
- package/lib/kernel/laplacianOfGaussian.js +1 -7
- package/lib/node_modules/test/binary.js +0 -3
- package/lib/node_modules/test/oneRoi.js +0 -2
- package/lib/stack/Stack.js +2 -35
- package/lib/stack/compute/histogram.js +0 -4
- package/lib/stack/compute/histograms.js +0 -4
- package/lib/stack/compute/max.js +0 -3
- package/lib/stack/compute/median.js +0 -4
- package/lib/stack/compute/min.js +0 -3
- package/lib/stack/extend.js +1 -11
- package/lib/stack/transform/matchAndCrop.js +6 -19
- package/lib/stack/utility/averageImage.js +0 -9
- package/lib/stack/utility/maxImage.js +0 -7
- package/lib/stack/utility/minImage.js +0 -7
- package/lib/util/Shape.js +3 -40
- package/lib/util/base64.js +3 -14
- package/lib/util/channel.js +1 -35
- package/lib/util/color.js +1 -25
- package/lib/util/converter.js +1 -13
- package/lib/util/deepValue.js +0 -3
- package/lib/util/histogram.js +1 -12
- package/lib/util/kernel.js +2 -12
- package/lib/util/matrix.js +0 -13
- package/lib/util/points.js +12 -35
- package/lib/util/value.js +0 -7
- package/lib/util/zerosMatrix.js +0 -3
- package/package.json +1 -1
- package/src/image/utility/setMatrix.js +4 -0
|
@@ -4,17 +4,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = resize;
|
|
7
|
-
|
|
8
7
|
var _converter = require("../../../util/converter");
|
|
9
|
-
|
|
10
8
|
var _Image = _interopRequireDefault(require("../../Image"));
|
|
11
|
-
|
|
12
9
|
var _checks = require("../../internal/checks");
|
|
13
|
-
|
|
14
10
|
var _nearestNeighbor = _interopRequireDefault(require("./nearestNeighbor"));
|
|
15
|
-
|
|
16
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
-
|
|
18
12
|
/**
|
|
19
13
|
* Resize an image
|
|
20
14
|
* @memberof Image
|
|
@@ -36,7 +30,6 @@ function resize(options = {}) {
|
|
|
36
30
|
const interpolationToUse = (0, _checks.checkInterpolation)(interpolation);
|
|
37
31
|
let width = options.width;
|
|
38
32
|
let height = options.height;
|
|
39
|
-
|
|
40
33
|
if (!width) {
|
|
41
34
|
if (height && preserveAspectRatio) {
|
|
42
35
|
width = Math.round(height * (this.width / this.height));
|
|
@@ -44,7 +37,6 @@ function resize(options = {}) {
|
|
|
44
37
|
width = this.width;
|
|
45
38
|
}
|
|
46
39
|
}
|
|
47
|
-
|
|
48
40
|
if (!height) {
|
|
49
41
|
if (preserveAspectRatio) {
|
|
50
42
|
height = Math.round(width * (this.height / this.width));
|
|
@@ -52,36 +44,28 @@ function resize(options = {}) {
|
|
|
52
44
|
height = this.height;
|
|
53
45
|
}
|
|
54
46
|
}
|
|
55
|
-
|
|
56
47
|
({
|
|
57
48
|
width,
|
|
58
49
|
height
|
|
59
50
|
} = (0, _converter.factorDimensions)(factor, width, height));
|
|
60
|
-
|
|
61
51
|
if (width === this.width && height === this.height) {
|
|
62
52
|
const newImage = this.clone();
|
|
63
53
|
newImage.position = [0, 0];
|
|
64
54
|
return newImage;
|
|
65
55
|
}
|
|
66
|
-
|
|
67
56
|
let shiftX = Math.round((this.width - width) / 2);
|
|
68
57
|
let shiftY = Math.round((this.height - height) / 2);
|
|
69
|
-
|
|
70
58
|
const newImage = _Image.default.createFrom(this, {
|
|
71
59
|
width,
|
|
72
60
|
height,
|
|
73
61
|
position: [shiftX, shiftY]
|
|
74
62
|
});
|
|
75
|
-
|
|
76
63
|
switch (interpolationToUse) {
|
|
77
64
|
case _checks.validInterpolations.nearestneighbor:
|
|
78
65
|
_nearestNeighbor.default.call(this, newImage, width, height);
|
|
79
|
-
|
|
80
66
|
break;
|
|
81
|
-
|
|
82
67
|
default:
|
|
83
68
|
throw new Error(`unsupported resize interpolation: ${interpolationToUse}`);
|
|
84
69
|
}
|
|
85
|
-
|
|
86
70
|
return newImage;
|
|
87
71
|
}
|
|
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = rgba;
|
|
7
|
-
|
|
8
7
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
9
|
-
|
|
10
8
|
var _model = require("../model/model");
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* Make a copy of the current image and convert to RGBA
|
|
16
12
|
* The source image must have RGB color model, 8 or 16 bits.
|
|
@@ -28,18 +24,14 @@ function rgba() {
|
|
|
28
24
|
alpha: [0, 1],
|
|
29
25
|
colorModel: [_model.RGB]
|
|
30
26
|
});
|
|
31
|
-
|
|
32
27
|
if (this.colorModel === _model.RGB && this.alpha) {
|
|
33
28
|
return this.clone();
|
|
34
29
|
}
|
|
35
|
-
|
|
36
30
|
let newImage = _Image.default.createFrom(this, {
|
|
37
31
|
alpha: 1
|
|
38
32
|
});
|
|
39
|
-
|
|
40
33
|
let ptr = 0;
|
|
41
34
|
let data = this.data;
|
|
42
|
-
|
|
43
35
|
for (let i = 0; i < data.length; i += this.channels) {
|
|
44
36
|
newImage.data[ptr++] = data[i];
|
|
45
37
|
newImage.data[ptr++] = data[i + 1];
|
|
@@ -47,6 +39,5 @@ function rgba() {
|
|
|
47
39
|
newImage.data[ptr++] = this.maxValue;
|
|
48
40
|
ptr++;
|
|
49
41
|
}
|
|
50
|
-
|
|
51
42
|
return newImage;
|
|
52
43
|
}
|
|
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = rgba8;
|
|
7
|
-
|
|
8
7
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
9
|
-
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
|
|
12
9
|
/**
|
|
13
10
|
* Make a copy of the current image and convert to RGBA 8 bits
|
|
14
11
|
* Those images are the one that are displayed in a canvas.
|
|
@@ -6,13 +6,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.rotate = rotate;
|
|
7
7
|
exports.rotateLeft = rotateLeft;
|
|
8
8
|
exports.rotateRight = rotateRight;
|
|
9
|
-
|
|
10
9
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
11
|
-
|
|
12
10
|
var _rotateFree = _interopRequireDefault(require("./rotateFree"));
|
|
13
|
-
|
|
14
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
12
|
/**
|
|
17
13
|
* Rotates an image.
|
|
18
14
|
* @memberof Image
|
|
@@ -26,28 +22,21 @@ function rotate(angle, options) {
|
|
|
26
22
|
this.checkProcessable('rotate', {
|
|
27
23
|
bitDepth: [1, 8, 16]
|
|
28
24
|
});
|
|
29
|
-
|
|
30
25
|
if (typeof angle !== 'number') {
|
|
31
26
|
throw new TypeError('angle must be a number');
|
|
32
27
|
}
|
|
33
|
-
|
|
34
28
|
if (angle < 0) {
|
|
35
29
|
angle = Math.ceil(-angle / 360) * 360 + angle;
|
|
36
30
|
}
|
|
37
|
-
|
|
38
31
|
switch (angle % 360) {
|
|
39
32
|
case 0:
|
|
40
33
|
return this.clone();
|
|
41
|
-
|
|
42
34
|
case 90:
|
|
43
35
|
return rotateRight.call(this);
|
|
44
|
-
|
|
45
36
|
case 180:
|
|
46
37
|
return rotate180.call(this);
|
|
47
|
-
|
|
48
38
|
case 270:
|
|
49
39
|
return rotateLeft.call(this);
|
|
50
|
-
|
|
51
40
|
default:
|
|
52
41
|
return _rotateFree.default.call(this, angle, options);
|
|
53
42
|
}
|
|
@@ -59,7 +48,6 @@ function rotate(angle, options) {
|
|
|
59
48
|
* @return {Image} The new rotated image
|
|
60
49
|
*/
|
|
61
50
|
|
|
62
|
-
|
|
63
51
|
function rotateLeft() {
|
|
64
52
|
if (this.bitDepth === 1) {
|
|
65
53
|
const newImage = new _Image.default(this.height, this.width, {
|
|
@@ -67,7 +55,6 @@ function rotateLeft() {
|
|
|
67
55
|
parent: this
|
|
68
56
|
});
|
|
69
57
|
const newMaxHeight = newImage.height - 1;
|
|
70
|
-
|
|
71
58
|
for (let i = 0; i < this.height; i++) {
|
|
72
59
|
for (let j = 0; j < this.width; j++) {
|
|
73
60
|
if (this.getBitXY(j, i)) {
|
|
@@ -75,16 +62,13 @@ function rotateLeft() {
|
|
|
75
62
|
}
|
|
76
63
|
}
|
|
77
64
|
}
|
|
78
|
-
|
|
79
65
|
return newImage;
|
|
80
66
|
} else {
|
|
81
67
|
const newImage = _Image.default.createFrom(this, {
|
|
82
68
|
width: this.height,
|
|
83
69
|
height: this.width
|
|
84
70
|
});
|
|
85
|
-
|
|
86
71
|
const newMaxHeight = newImage.height - 1;
|
|
87
|
-
|
|
88
72
|
for (let i = 0; i < this.height; i++) {
|
|
89
73
|
for (let j = 0; j < this.width; j++) {
|
|
90
74
|
for (let k = 0; k < this.channels; k++) {
|
|
@@ -92,7 +76,6 @@ function rotateLeft() {
|
|
|
92
76
|
}
|
|
93
77
|
}
|
|
94
78
|
}
|
|
95
|
-
|
|
96
79
|
return newImage;
|
|
97
80
|
}
|
|
98
81
|
}
|
|
@@ -103,7 +86,6 @@ function rotateLeft() {
|
|
|
103
86
|
* @return {Image} The new rotated image
|
|
104
87
|
*/
|
|
105
88
|
|
|
106
|
-
|
|
107
89
|
function rotateRight() {
|
|
108
90
|
if (this.bitDepth === 1) {
|
|
109
91
|
const newImage = new _Image.default(this.height, this.width, {
|
|
@@ -111,7 +93,6 @@ function rotateRight() {
|
|
|
111
93
|
parent: this
|
|
112
94
|
});
|
|
113
95
|
const newMaxWidth = newImage.width - 1;
|
|
114
|
-
|
|
115
96
|
for (let i = 0; i < this.height; i++) {
|
|
116
97
|
for (let j = 0; j < this.width; j++) {
|
|
117
98
|
if (this.getBitXY(j, i)) {
|
|
@@ -119,16 +100,13 @@ function rotateRight() {
|
|
|
119
100
|
}
|
|
120
101
|
}
|
|
121
102
|
}
|
|
122
|
-
|
|
123
103
|
return newImage;
|
|
124
104
|
} else {
|
|
125
105
|
const newImage = _Image.default.createFrom(this, {
|
|
126
106
|
width: this.height,
|
|
127
107
|
height: this.width
|
|
128
108
|
});
|
|
129
|
-
|
|
130
109
|
const newMaxWidth = newImage.width - 1;
|
|
131
|
-
|
|
132
110
|
for (let i = 0; i < this.height; i++) {
|
|
133
111
|
for (let j = 0; j < this.width; j++) {
|
|
134
112
|
for (let k = 0; k < this.channels; k++) {
|
|
@@ -136,11 +114,9 @@ function rotateRight() {
|
|
|
136
114
|
}
|
|
137
115
|
}
|
|
138
116
|
}
|
|
139
|
-
|
|
140
117
|
return newImage;
|
|
141
118
|
}
|
|
142
119
|
}
|
|
143
|
-
|
|
144
120
|
function rotate180() {
|
|
145
121
|
if (this.bitDepth === 1) {
|
|
146
122
|
const newImage = new _Image.default(this.width, this.height, {
|
|
@@ -149,7 +125,6 @@ function rotate180() {
|
|
|
149
125
|
});
|
|
150
126
|
const newMaxWidth = newImage.width - 1;
|
|
151
127
|
const newMaxHeight = newImage.height - 1;
|
|
152
|
-
|
|
153
128
|
for (let i = 0; i < this.height; i++) {
|
|
154
129
|
for (let j = 0; j < this.width; j++) {
|
|
155
130
|
if (this.getBitXY(j, i)) {
|
|
@@ -157,14 +132,11 @@ function rotate180() {
|
|
|
157
132
|
}
|
|
158
133
|
}
|
|
159
134
|
}
|
|
160
|
-
|
|
161
135
|
return newImage;
|
|
162
136
|
} else {
|
|
163
137
|
const newImage = _Image.default.createFrom(this);
|
|
164
|
-
|
|
165
138
|
const newMaxWidth = newImage.width - 1;
|
|
166
139
|
const newMaxHeight = newImage.height - 1;
|
|
167
|
-
|
|
168
140
|
for (let i = 0; i < this.height; i++) {
|
|
169
141
|
for (let j = 0; j < this.width; j++) {
|
|
170
142
|
for (let k = 0; k < this.channels; k++) {
|
|
@@ -172,7 +144,6 @@ function rotate180() {
|
|
|
172
144
|
}
|
|
173
145
|
}
|
|
174
146
|
}
|
|
175
|
-
|
|
176
147
|
return newImage;
|
|
177
148
|
}
|
|
178
149
|
}
|
|
@@ -4,24 +4,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = rotateFree;
|
|
7
|
-
|
|
8
7
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
9
|
-
|
|
10
8
|
var _checks = require("../internal/checks");
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
function rotateFree(degrees, options = {}) {
|
|
15
11
|
const {
|
|
16
12
|
interpolation = _checks.validInterpolations.nearestneighbor,
|
|
17
13
|
width = this.width,
|
|
18
14
|
height = this.height
|
|
19
15
|
} = options;
|
|
20
|
-
|
|
21
16
|
if (typeof degrees !== 'number') {
|
|
22
17
|
throw new TypeError('degrees must be a number');
|
|
23
18
|
}
|
|
24
|
-
|
|
25
19
|
const interpolationToUse = (0, _checks.checkInterpolation)(interpolation);
|
|
26
20
|
const radians = degrees * Math.PI / 180;
|
|
27
21
|
const newWidth = Math.floor(Math.abs(width * Math.cos(radians)) + Math.abs(height * Math.sin(radians)));
|
|
@@ -30,10 +24,8 @@ function rotateFree(degrees, options = {}) {
|
|
|
30
24
|
const sin = Math.sin(-radians);
|
|
31
25
|
let x0 = newWidth / 2;
|
|
32
26
|
let y0 = newHeight / 2;
|
|
33
|
-
|
|
34
27
|
if (newWidth % 2 === 0) {
|
|
35
28
|
x0 = x0 - 0.5;
|
|
36
|
-
|
|
37
29
|
if (newHeight % 2 === 0) {
|
|
38
30
|
y0 = y0 - 0.5;
|
|
39
31
|
} else {
|
|
@@ -41,30 +33,24 @@ function rotateFree(degrees, options = {}) {
|
|
|
41
33
|
}
|
|
42
34
|
} else {
|
|
43
35
|
x0 = Math.floor(x0);
|
|
44
|
-
|
|
45
36
|
if (newHeight % 2 === 0) {
|
|
46
37
|
y0 = y0 - 0.5;
|
|
47
38
|
} else {
|
|
48
39
|
y0 = Math.floor(y0);
|
|
49
40
|
}
|
|
50
41
|
}
|
|
51
|
-
|
|
52
42
|
const incrementX = Math.floor(width / 2 - x0);
|
|
53
43
|
const incrementY = Math.floor(height / 2 - y0);
|
|
54
|
-
|
|
55
44
|
if (this.bitDepth === 1) {
|
|
56
45
|
const newImage = new _Image.default(newWidth, newHeight, {
|
|
57
46
|
kind: 'BINARY',
|
|
58
47
|
parent: this
|
|
59
48
|
});
|
|
60
|
-
|
|
61
49
|
switch (interpolationToUse) {
|
|
62
50
|
case _checks.validInterpolations.nearestneighbor:
|
|
63
51
|
return rotateBinaryNearestNeighbor(this, newImage, incrementX, incrementY, x0, y0, cos, sin);
|
|
64
|
-
|
|
65
52
|
case _checks.validInterpolations.bilinear:
|
|
66
53
|
return rotateBinaryBilinear(this, newImage, incrementX, incrementY, x0, y0, cos, sin);
|
|
67
|
-
|
|
68
54
|
default:
|
|
69
55
|
throw new Error(`unsupported rotate interpolation: ${interpolationToUse}`);
|
|
70
56
|
}
|
|
@@ -73,27 +59,22 @@ function rotateFree(degrees, options = {}) {
|
|
|
73
59
|
width: newWidth,
|
|
74
60
|
height: newHeight
|
|
75
61
|
});
|
|
76
|
-
|
|
77
62
|
switch (interpolationToUse) {
|
|
78
63
|
case _checks.validInterpolations.nearestneighbor:
|
|
79
64
|
return rotateNearestNeighbor(this, newImage, incrementX, incrementY, x0, y0, cos, sin);
|
|
80
|
-
|
|
81
65
|
case _checks.validInterpolations.bilinear:
|
|
82
66
|
return rotateBilinear(this, newImage, incrementX, incrementY, x0, y0, cos, sin);
|
|
83
|
-
|
|
84
67
|
default:
|
|
85
68
|
throw new Error(`unsupported rotate interpolation: ${interpolationToUse}`);
|
|
86
69
|
}
|
|
87
70
|
}
|
|
88
71
|
}
|
|
89
|
-
|
|
90
72
|
function rotateNearestNeighbor(thisImage, newImage, incrementX, incrementY, x0, y0, cos, sin) {
|
|
91
73
|
for (let i = 0; i < newImage.width; i += 1) {
|
|
92
74
|
for (let j = 0; j < newImage.height; j += 1) {
|
|
93
75
|
for (let c = 0; c < thisImage.channels; c++) {
|
|
94
76
|
let x = Math.round((i - x0) * cos - (j - y0) * sin + x0) + incrementX;
|
|
95
77
|
let y = Math.round((j - y0) * cos + (i - x0) * sin + y0) + incrementY;
|
|
96
|
-
|
|
97
78
|
if (x < 0 || x >= thisImage.width || y < 0 || y >= thisImage.height) {
|
|
98
79
|
if (thisImage.alpha === 1 && c === thisImage.channels - 1) {
|
|
99
80
|
newImage.setValueXY(i, j, c, 0);
|
|
@@ -106,28 +87,22 @@ function rotateNearestNeighbor(thisImage, newImage, incrementX, incrementY, x0,
|
|
|
106
87
|
}
|
|
107
88
|
}
|
|
108
89
|
}
|
|
109
|
-
|
|
110
90
|
return newImage;
|
|
111
91
|
}
|
|
112
|
-
|
|
113
92
|
function rotateBinaryNearestNeighbor(thisImage, newImage, incrementX, incrementY, x0, y0, cos, sin) {
|
|
114
93
|
for (let i = 0; i < newImage.width; i += 1) {
|
|
115
94
|
for (let j = 0; j < newImage.height; j += 1) {
|
|
116
95
|
let x = Math.round((i - x0) * cos - (j - y0) * sin + x0) + incrementX;
|
|
117
96
|
let y = Math.round((j - y0) * cos + (i - x0) * sin + y0) + incrementY;
|
|
118
|
-
|
|
119
97
|
if (x < 0 || x >= thisImage.width || y < 0 || y >= thisImage.height || thisImage.getBitXY(x, y)) {
|
|
120
98
|
newImage.setBitXY(i, j);
|
|
121
99
|
}
|
|
122
100
|
}
|
|
123
101
|
}
|
|
124
|
-
|
|
125
102
|
return newImage;
|
|
126
103
|
}
|
|
127
|
-
|
|
128
104
|
function rotateBilinear(thisImage, newImage, incrementX, incrementY, x0, y0, cos, sin) {
|
|
129
105
|
let stride = thisImage.width * thisImage.channels;
|
|
130
|
-
|
|
131
106
|
for (let j = 0; j < newImage.height; j++) {
|
|
132
107
|
for (let i = 0; i < newImage.width; i++) {
|
|
133
108
|
let x = (i - x0) * cos - (j - y0) * sin + x0 + incrementX;
|
|
@@ -136,7 +111,6 @@ function rotateBilinear(thisImage, newImage, incrementX, incrementY, x0, y0, cos
|
|
|
136
111
|
let y1 = y | 0;
|
|
137
112
|
let xDiff = x - x1;
|
|
138
113
|
let yDiff = y - y1;
|
|
139
|
-
|
|
140
114
|
for (let c = 0; c < thisImage.channels; c++) {
|
|
141
115
|
if (x < 0 || x >= thisImage.width || y < 0 || y >= thisImage.height) {
|
|
142
116
|
if (thisImage.alpha === 1 && c === thisImage.channels - 1) {
|
|
@@ -156,13 +130,10 @@ function rotateBilinear(thisImage, newImage, incrementX, incrementY, x0, y0, cos
|
|
|
156
130
|
}
|
|
157
131
|
}
|
|
158
132
|
}
|
|
159
|
-
|
|
160
133
|
return newImage;
|
|
161
134
|
}
|
|
162
|
-
|
|
163
135
|
function rotateBinaryBilinear(thisImage, newImage, incrementX, incrementY, x0, y0, cos, sin) {
|
|
164
136
|
let stride = thisImage.width;
|
|
165
|
-
|
|
166
137
|
for (let j = 0; j < newImage.height; j++) {
|
|
167
138
|
for (let i = 0; i < newImage.width; i++) {
|
|
168
139
|
let x = (i - x0) * cos - (j - y0) * sin + x0 + incrementX;
|
|
@@ -171,7 +142,6 @@ function rotateBinaryBilinear(thisImage, newImage, incrementX, incrementY, x0, y
|
|
|
171
142
|
let y1 = y | 0;
|
|
172
143
|
let xDiff = x - x1;
|
|
173
144
|
let yDiff = y - y1;
|
|
174
|
-
|
|
175
145
|
if (x < 0 || x >= thisImage.width || y < 0 || y >= thisImage.height) {
|
|
176
146
|
newImage.setBitXY(i, j);
|
|
177
147
|
} else {
|
|
@@ -185,6 +155,5 @@ function rotateBinaryBilinear(thisImage, newImage, incrementX, incrementY, x0, y
|
|
|
185
155
|
}
|
|
186
156
|
}
|
|
187
157
|
}
|
|
188
|
-
|
|
189
158
|
return newImage;
|
|
190
159
|
}
|
|
@@ -4,18 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = warpingFourPoints;
|
|
7
|
-
|
|
8
7
|
var _mlMatrix = require("ml-matrix");
|
|
9
|
-
|
|
10
8
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
// REFERENCES :
|
|
15
11
|
// https://stackoverflow.com/questions/38285229/calculating-aspect-ratio-of-perspective-transform-destination-image/38402378#38402378
|
|
16
12
|
// http://www.corrmap.com/features/homography_transformation.php
|
|
17
13
|
// https://ags.cs.uni-kl.de/fileadmin/inf_ags/3dcv-ws11-12/3DCV_WS11-12_lec04.pdf
|
|
18
14
|
// http://graphics.cs.cmu.edu/courses/15-463/2011_fall/Lectures/morphing.pdf
|
|
15
|
+
|
|
19
16
|
function order4Points(pts) {
|
|
20
17
|
let tl = 0;
|
|
21
18
|
let tr = 0;
|
|
@@ -23,28 +20,23 @@ function order4Points(pts) {
|
|
|
23
20
|
let bl = 0;
|
|
24
21
|
let minX = pts[0][0];
|
|
25
22
|
let indexMinX = 0;
|
|
26
|
-
|
|
27
23
|
for (let i = 1; i < pts.length; i++) {
|
|
28
24
|
if (pts[i][0] < minX) {
|
|
29
25
|
minX = pts[i][0];
|
|
30
26
|
indexMinX = i;
|
|
31
27
|
}
|
|
32
28
|
}
|
|
33
|
-
|
|
34
29
|
let minX2 = pts[(indexMinX + 1) % pts.length][0];
|
|
35
30
|
let indexMinX2 = (indexMinX + 1) % pts.length;
|
|
36
|
-
|
|
37
31
|
for (let i = 1; i < pts.length; i++) {
|
|
38
32
|
if (pts[i][0] < minX2 && i !== indexMinX) {
|
|
39
33
|
minX2 = pts[i][0];
|
|
40
34
|
indexMinX2 = i;
|
|
41
35
|
}
|
|
42
36
|
}
|
|
43
|
-
|
|
44
37
|
if (pts[indexMinX2][1] < pts[indexMinX][1]) {
|
|
45
38
|
tl = pts[indexMinX2];
|
|
46
39
|
bl = pts[indexMinX];
|
|
47
|
-
|
|
48
40
|
if (indexMinX !== (indexMinX2 + 1) % 4) {
|
|
49
41
|
tr = pts[(indexMinX2 + 1) % 4];
|
|
50
42
|
br = pts[(indexMinX2 + 2) % 4];
|
|
@@ -55,7 +47,6 @@ function order4Points(pts) {
|
|
|
55
47
|
} else {
|
|
56
48
|
bl = pts[indexMinX2];
|
|
57
49
|
tl = pts[indexMinX];
|
|
58
|
-
|
|
59
50
|
if (indexMinX2 !== (indexMinX + 1) % 4) {
|
|
60
51
|
tr = pts[(indexMinX + 1) % 4];
|
|
61
52
|
br = pts[(indexMinX + 2) % 4];
|
|
@@ -64,24 +55,19 @@ function order4Points(pts) {
|
|
|
64
55
|
br = pts[(indexMinX + 3) % 4];
|
|
65
56
|
}
|
|
66
57
|
}
|
|
67
|
-
|
|
68
58
|
return [tl, tr, br, bl];
|
|
69
59
|
}
|
|
70
|
-
|
|
71
60
|
function distance2Points(p1, p2) {
|
|
72
61
|
return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));
|
|
73
62
|
}
|
|
74
|
-
|
|
75
63
|
function crossVect(u, v) {
|
|
76
64
|
let result = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];
|
|
77
65
|
return result;
|
|
78
66
|
}
|
|
79
|
-
|
|
80
67
|
function dotVect(u, v) {
|
|
81
68
|
let result = u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
|
|
82
69
|
return result;
|
|
83
70
|
}
|
|
84
|
-
|
|
85
71
|
function computeWidthAndHeigth(tl, tr, br, bl, widthImage, heightImage) {
|
|
86
72
|
let w = Math.max(distance2Points(tl, tr), distance2Points(bl, br));
|
|
87
73
|
let h = Math.max(distance2Points(tl, bl), distance2Points(tr, br));
|
|
@@ -105,24 +91,18 @@ function computeWidthAndHeigth(tl, tr, br, bl, widthImage, heightImage) {
|
|
|
105
91
|
let n32 = n3[1];
|
|
106
92
|
let n33 = n3[2];
|
|
107
93
|
let f = 1.0 / (n23 * n33) * (n21 * n31 - (n21 * n33 + n23 * n31) * u0 + n23 * n33 * u0 * u0 + (n22 * n32 - (n22 * n33 + n23 * n32) * v0 + n23 * n33 * v0 * v0));
|
|
108
|
-
|
|
109
94
|
if (f >= 0) {
|
|
110
95
|
f = Math.sqrt(f);
|
|
111
96
|
} else {
|
|
112
97
|
f = Math.sqrt(-f);
|
|
113
98
|
}
|
|
114
|
-
|
|
115
99
|
let A = new _mlMatrix.Matrix([[f, 0, u0], [0, f, v0], [0, 0, 1]]);
|
|
116
100
|
let At = A.transpose();
|
|
117
101
|
let Ati = (0, _mlMatrix.inverse)(At);
|
|
118
102
|
let Ai = (0, _mlMatrix.inverse)(A);
|
|
119
|
-
|
|
120
103
|
let n2R = _mlMatrix.Matrix.rowVector(n2);
|
|
121
|
-
|
|
122
104
|
let n3R = _mlMatrix.Matrix.rowVector(n3);
|
|
123
|
-
|
|
124
105
|
let arReal = Math.sqrt(dotVect(n2R.mmul(Ati).mmul(Ai).to1DArray(), n2) / dotVect(n3R.mmul(Ati).mmul(Ai).to1DArray(), n3));
|
|
125
|
-
|
|
126
106
|
if (arReal === 0 || arVis === 0) {
|
|
127
107
|
finalW = Math.ceil(w);
|
|
128
108
|
finalH = Math.ceil(h);
|
|
@@ -133,14 +113,13 @@ function computeWidthAndHeigth(tl, tr, br, bl, widthImage, heightImage) {
|
|
|
133
113
|
finalH = Math.ceil(h);
|
|
134
114
|
finalW = Math.ceil(arReal * finalH);
|
|
135
115
|
}
|
|
136
|
-
|
|
137
116
|
return [finalW, finalH];
|
|
138
117
|
}
|
|
139
|
-
|
|
140
118
|
function projectionPoint(x, y, a, b, c, d, e, f, g, h, image, channel) {
|
|
141
119
|
let [newX, newY] = [(a * x + b * y + c) / (g * x + h * y + 1), (d * x + e * y + f) / (g * x + h * y + 1)];
|
|
142
120
|
return image.getValueXY(Math.floor(newX), Math.floor(newY), channel);
|
|
143
121
|
}
|
|
122
|
+
|
|
144
123
|
/**
|
|
145
124
|
* Transform a quadrilateral into a rectangle
|
|
146
125
|
* @memberof Image
|
|
@@ -155,34 +134,28 @@ function projectionPoint(x, y, a, b, c, d, e, f, g, h, image, channel) {
|
|
|
155
134
|
* });
|
|
156
135
|
*/
|
|
157
136
|
|
|
158
|
-
|
|
159
137
|
function warpingFourPoints(pts, options = {}) {
|
|
160
138
|
let {
|
|
161
139
|
calculateRatio = true
|
|
162
140
|
} = options;
|
|
163
|
-
|
|
164
141
|
if (pts.length !== 4) {
|
|
165
142
|
throw new Error(`The array pts must have four elements, which are the four corners. Currently, pts have ${pts.length} elements`);
|
|
166
143
|
}
|
|
167
|
-
|
|
168
144
|
let [pt1, pt2, pt3, pt4] = pts;
|
|
169
145
|
let quadrilaterial = [pt1, pt2, pt3, pt4];
|
|
170
146
|
let [tl, tr, br, bl] = order4Points(quadrilaterial);
|
|
171
147
|
let widthRect;
|
|
172
148
|
let heightRect;
|
|
173
|
-
|
|
174
149
|
if (calculateRatio) {
|
|
175
150
|
[widthRect, heightRect] = computeWidthAndHeigth(tl, tr, br, bl, this.width, this.height);
|
|
176
151
|
} else {
|
|
177
152
|
widthRect = Math.ceil(Math.max(distance2Points(tl, tr), distance2Points(bl, br)));
|
|
178
153
|
heightRect = Math.ceil(Math.max(distance2Points(tl, bl), distance2Points(tr, br)));
|
|
179
154
|
}
|
|
180
|
-
|
|
181
155
|
let newImage = _Image.default.createFrom(this, {
|
|
182
156
|
width: widthRect,
|
|
183
157
|
height: heightRect
|
|
184
158
|
});
|
|
185
|
-
|
|
186
159
|
let [X1, Y1] = tl;
|
|
187
160
|
let [X2, Y2] = tr;
|
|
188
161
|
let [X3, Y3] = br;
|
|
@@ -192,26 +165,20 @@ function warpingFourPoints(pts, options = {}) {
|
|
|
192
165
|
let [x3, y3] = [heightRect - 1, widthRect - 1];
|
|
193
166
|
let [x4, y4] = [heightRect - 1, 0];
|
|
194
167
|
let S = new _mlMatrix.Matrix([[x1, y1, 1, 0, 0, 0, -x1 * X1, -y1 * X1], [x2, y2, 1, 0, 0, 0, -x2 * X2, -y2 * X2], [x3, y3, 1, 0, 0, 0, -x3 * X3, -y1 * X3], [x4, y4, 1, 0, 0, 0, -x4 * X4, -y4 * X4], [0, 0, 0, x1, y1, 1, -x1 * Y1, -y1 * Y1], [0, 0, 0, x2, y2, 1, -x2 * Y2, -y2 * Y2], [0, 0, 0, x3, y3, 1, -x3 * Y3, -y3 * Y3], [0, 0, 0, x4, y4, 1, -x4 * Y4, -y4 * Y4]]);
|
|
195
|
-
|
|
196
168
|
let D = _mlMatrix.Matrix.columnVector([X1, X2, X3, X4, Y1, Y2, Y3, Y4]);
|
|
197
|
-
|
|
198
169
|
let svd = new _mlMatrix.SingularValueDecomposition(S);
|
|
199
170
|
let T = svd.solve(D); // solve S*T = D
|
|
200
|
-
|
|
201
171
|
let [a, b, c, d, e, f, g, h] = T.to1DArray();
|
|
202
172
|
let Xt = new _mlMatrix.Matrix(heightRect, widthRect);
|
|
203
|
-
|
|
204
173
|
for (let channel = 0; channel < this.channels; channel++) {
|
|
205
174
|
for (let i = 0; i < heightRect; i++) {
|
|
206
175
|
for (let j = 0; j < widthRect; j++) {
|
|
207
176
|
Xt.set(i, j, projectionPoint(i, j, a, b, c, d, e, f, g, h, this, channel));
|
|
208
177
|
}
|
|
209
178
|
}
|
|
210
|
-
|
|
211
179
|
newImage.setMatrix(Xt, {
|
|
212
180
|
channel: channel
|
|
213
181
|
});
|
|
214
182
|
}
|
|
215
|
-
|
|
216
183
|
return newImage;
|
|
217
184
|
}
|
|
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = combineChannels;
|
|
7
|
-
|
|
8
7
|
var _Image = _interopRequireDefault(require("../Image"));
|
|
9
|
-
|
|
10
8
|
var _model = require("../model/model");
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* Create a new grey Image by combining the channels of the current image.
|
|
16
12
|
* @memberof Image
|
|
@@ -31,33 +27,26 @@ function combineChannels(method = defaultCombineMethod, options = {}) {
|
|
|
31
27
|
this.checkProcessable('combineChannels', {
|
|
32
28
|
bitDepth: [8, 16]
|
|
33
29
|
});
|
|
34
|
-
|
|
35
30
|
let newImage = _Image.default.createFrom(this, {
|
|
36
31
|
components: 1,
|
|
37
32
|
alpha: keepAlpha,
|
|
38
33
|
colorModel: _model.GREY
|
|
39
34
|
});
|
|
40
|
-
|
|
41
35
|
let ptr = 0;
|
|
42
|
-
|
|
43
36
|
for (let i = 0; i < this.size; i++) {
|
|
44
37
|
// TODO quite slow because we create a new pixel each time
|
|
45
38
|
let value = method(this.getPixel(i));
|
|
46
|
-
|
|
47
39
|
if (mergeAlpha) {
|
|
48
40
|
newImage.data[ptr++] = value * this.data[i * this.channels + this.components] / this.maxValue;
|
|
49
41
|
} else {
|
|
50
42
|
newImage.data[ptr++] = value;
|
|
51
|
-
|
|
52
43
|
if (keepAlpha) {
|
|
53
44
|
newImage.data[ptr++] = this.data[i * this.channels + this.components];
|
|
54
45
|
}
|
|
55
46
|
}
|
|
56
47
|
}
|
|
57
|
-
|
|
58
48
|
return newImage;
|
|
59
49
|
}
|
|
60
|
-
|
|
61
50
|
function defaultCombineMethod(pixel) {
|
|
62
51
|
return (pixel[0] + pixel[1] + pixel[2]) / 3;
|
|
63
52
|
}
|