mirror of
https://github.com/publiclab/image-sequencer.git
synced 2025-12-13 11:50:02 +01:00
Compare commits
25 Commits
dependabot
...
tape-run-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
373914f01e | ||
|
|
2914aaef70 | ||
|
|
e2dd5a7309 | ||
|
|
eb497e1a62 | ||
|
|
8a929c4b4d | ||
|
|
b95af7672c | ||
|
|
eb5672c433 | ||
|
|
c0b9f88818 | ||
|
|
4810a3b975 | ||
|
|
07c6d1497a | ||
|
|
8ddf05f0bc | ||
|
|
456a22a845 | ||
|
|
740693b655 | ||
|
|
23ddf1fce0 | ||
|
|
b7eb9cfc45 | ||
|
|
da9b167258 | ||
|
|
3b6eac4a96 | ||
|
|
8367f4bc26 | ||
|
|
a5abbeaf76 | ||
|
|
d55752827d | ||
|
|
1658220198 | ||
|
|
54722a35f7 | ||
|
|
eb381555c4 | ||
|
|
917979267a | ||
|
|
fb303a8ca9 |
7
.gitpod.dockerfile
Normal file
7
.gitpod.dockerfile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
FROM gitpod/workspace-full
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN sudo apt-get update && apt-get install -y apt-transport-https \
|
||||||
|
&& sudo apt-get install -y \
|
||||||
|
xserver-xorg-dev libxext-dev libxi-dev build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config libglu1-mesa-dev freeglut3-dev mesa-common-dev \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/*
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
image:
|
||||||
|
file: .gitpod.dockerfile
|
||||||
tasks:
|
tasks:
|
||||||
- init: npm run setup
|
- init: npm run setup
|
||||||
command: npm start
|
command: npm start
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
sudo: required
|
sudo: required
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '8'
|
|
||||||
- '10'
|
- '10'
|
||||||
|
- '12'
|
||||||
env:
|
env:
|
||||||
- CXX=g++-4.8
|
- CXX=g++-4.8
|
||||||
before_script:
|
before_script:
|
||||||
|
|||||||
@@ -2,13 +2,18 @@ Image Sequencer
|
|||||||
====
|
====
|
||||||
|
|
||||||
[](https://publiclab.org/conduct)
|
[](https://publiclab.org/conduct)
|
||||||
|
[](https://badge.fury.io/js/image-sequencer)
|
||||||
[](https://travis-ci.org/publiclab/image-sequencer) [](https://codeclimate.com/github/publiclab/image-sequencer/maintainability) [](https://codecov.io/gh/publiclab/image-sequencer)
|
[](https://travis-ci.org/publiclab/image-sequencer) [](https://codeclimate.com/github/publiclab/image-sequencer/maintainability) [](https://codecov.io/gh/publiclab/image-sequencer)
|
||||||
[](https://gitpod.io/from-referrer/)
|
[](https://gitpod.io/#https://github.com/publiclab/image-sequencer/)
|
||||||
|
|
||||||
- **Latest Stable Demo**: https://sequencer.publiclab.org
|
- **Latest Stable Demo**: https://sequencer.publiclab.org
|
||||||
- **Latest Beta Demo**: https://beta.sequencer.publiclab.org
|
- **Latest Beta Demo**: https://beta.sequencer.publiclab.org
|
||||||
- **Stable Branch**: https://github.com/publiclab/image-sequencer/tree/stable/
|
- **Stable Branch**: https://github.com/publiclab/image-sequencer/tree/stable/
|
||||||
|
|
||||||
|
Begin running (and contributing to) this codebase immediately with [GitPod](https://gitpod.io) (this also opens the latest `main` branch code):
|
||||||
|
|
||||||
|
[](https://gitpod.io/#https://github.com/publiclab/image-sequencer)
|
||||||
|
|
||||||
## Why
|
## Why
|
||||||
|
|
||||||
Image Sequencer is different from other image processing systems because it's _non-destructive_: instead of modifying the original image, it **creates a new image at each step in a sequence**. This is because it:
|
Image Sequencer is different from other image processing systems because it's _non-destructive_: instead of modifying the original image, it **creates a new image at each step in a sequence**. This is because it:
|
||||||
|
|||||||
@@ -218,7 +218,7 @@
|
|||||||
<h2>Need Help?</h2>
|
<h2>Need Help?</h2>
|
||||||
<p>
|
<p>
|
||||||
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer/issues">Ask a question</a>
|
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer/issues">Ask a question</a>
|
||||||
<a class="btn btn-default" href="https://publiclab.org/chat">Ask in our chatroom</a>
|
<a class="btn btn-default" href="https://gitter.im/publiclab/image-sequencer" target="_blank">Ask in our chatroom </a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
|
|||||||
function selectNewStepUi() {
|
function selectNewStepUi() {
|
||||||
var m = $(addStepSel + ' select').val();
|
var m = $(addStepSel + ' select').val();
|
||||||
if(!m) m = arguments[0];
|
if(!m) m = arguments[0];
|
||||||
$(addStepSel + ' .info').html(_sequencer.modulesInfo(m).description);
|
else $(addStepSel + ' .info').html(_sequencer.modulesInfo(m).description);
|
||||||
$(addStepSel + ' #add-step-btn').prop('disabled', false);
|
$(addStepSel + ' #add-step-btn').prop('disabled', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4439
package-lock.json
generated
4439
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -55,14 +55,14 @@
|
|||||||
"image-sequencer-invert": "^1.0.0",
|
"image-sequencer-invert": "^1.0.0",
|
||||||
"imagejs": "0.0.9",
|
"imagejs": "0.0.9",
|
||||||
"imagemin": "^7.0.1",
|
"imagemin": "^7.0.1",
|
||||||
"imagemin-jpegtran": "^6.0.0",
|
"imagemin-jpegtran": "^7.0.0",
|
||||||
"imagemin-pngquant": "^8.0.0",
|
"imagemin-pngquant": "^9.0.1",
|
||||||
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
|
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
|
||||||
"istanbul": "^0.4.5",
|
"istanbul": "^0.4.5",
|
||||||
"jasmine": "^3.4.0",
|
"jasmine": "^3.4.0",
|
||||||
"jpegtran-bin": "^4.0.0",
|
"jpegtran-bin": "^5.0.2",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
"jsdom": "^15.0.0",
|
"jsdom": "^16.3.0",
|
||||||
"jspdf": "^1.5.3",
|
"jspdf": "^1.5.3",
|
||||||
"jsqr": "^1.1.1",
|
"jsqr": "^1.1.1",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
@@ -100,14 +100,14 @@
|
|||||||
"jasmine-core": "^3.3.0",
|
"jasmine-core": "^3.3.0",
|
||||||
"jasmine-jquery": "^2.1.1",
|
"jasmine-jquery": "^2.1.1",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"jasmine-spec-reporter": "^4.2.1",
|
||||||
"jest": "^25.1.0",
|
"jest": "^26.1.0",
|
||||||
"jest-puppeteer": "^4.3.0",
|
"jest-puppeteer": "^4.3.0",
|
||||||
"lint-staged": "^10.0.3",
|
"lint-staged": "^10.0.3",
|
||||||
"looks-same": "^7.0.0",
|
"looks-same": "^7.0.0",
|
||||||
"matchdep": "^2.0.0",
|
"matchdep": "^2.0.0",
|
||||||
"tap-spec": "^5.0.0",
|
"tap-spec": "^5.0.0",
|
||||||
"tape": "^4.9.2",
|
"tape": "^4.9.2",
|
||||||
"tape-run": "^7.0.0",
|
"tape-run": "^8.0.0",
|
||||||
"uglify-es": "^3.3.7"
|
"uglify-es": "^3.3.7"
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
|
|||||||
@@ -14,10 +14,8 @@ const kernelx = [
|
|||||||
[ 1, 2, 1]
|
[ 1, 2, 1]
|
||||||
];
|
];
|
||||||
|
|
||||||
let pixelsToBeSupressed = [];
|
|
||||||
|
|
||||||
module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, useHysteresis) {
|
module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, useHysteresis) {
|
||||||
let angles = [], grads = [], strongEdgePixels = [], weakEdgePixels = [];
|
let angles = [], grads = [], strongEdgePixels = [], weakEdgePixels = [], pixelsToBeSupressed = [];
|
||||||
|
|
||||||
for (var x = 0; x < pixels.shape[0]; x++) {
|
for (var x = 0; x < pixels.shape[0]; x++) {
|
||||||
grads.push([]);
|
grads.push([]);
|
||||||
@@ -34,8 +32,8 @@ module.exports = function(pixels, highThresholdRatio, lowThresholdRatio, useHyst
|
|||||||
angles.slice(-1)[0].push(result.angle);
|
angles.slice(-1)[0].push(result.angle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nonMaxSupress(pixels, grads, angles); // Non Maximum Suppression: Filter fine edges.
|
nonMaxSupress(pixels, grads, angles, pixelsToBeSupressed); // Non Maximum Suppression: Filter fine edges.
|
||||||
doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio, grads, strongEdgePixels, weakEdgePixels); // Double Threshold: Categorizes edges into strong and weak edges based on two thresholds.
|
doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio, grads, strongEdgePixels, weakEdgePixels, pixelsToBeSupressed); // Double Threshold: Categorizes edges into strong and weak edges based on two thresholds.
|
||||||
if(useHysteresis.toLowerCase() == 'true') hysteresis(strongEdgePixels, weakEdgePixels); // Optional Hysteresis (very slow) to minimize edges generated due to noise.
|
if(useHysteresis.toLowerCase() == 'true') hysteresis(strongEdgePixels, weakEdgePixels); // Optional Hysteresis (very slow) to minimize edges generated due to noise.
|
||||||
|
|
||||||
strongEdgePixels.forEach(pixel => preserve(pixels, pixel)); // Makes the strong edges White.
|
strongEdgePixels.forEach(pixel => preserve(pixels, pixel)); // Makes the strong edges White.
|
||||||
@@ -144,7 +142,7 @@ const removeElem = (arr = [], elem) => { // Removes the specified element from t
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Non Maximum Supression without interpolation.
|
// Non Maximum Supression without interpolation.
|
||||||
function nonMaxSupress(pixels, grads, angles) {
|
function nonMaxSupress(pixels, grads, angles, pixelsToBeSupressed) {
|
||||||
angles = angles.map((arr) => arr.map(convertToDegrees));
|
angles = angles.map((arr) => arr.map(convertToDegrees));
|
||||||
|
|
||||||
for (let x = 0; x < pixels.shape[0]; x++) {
|
for (let x = 0; x < pixels.shape[0]; x++) {
|
||||||
@@ -196,7 +194,7 @@ var convertToDegrees = radians => (radians * 180) / Math.PI;
|
|||||||
var findMaxInMatrix = arr => Math.max(...arr.map(el => el.map(val => val ? val : 0)).map(el => Math.max(...el)));
|
var findMaxInMatrix = arr => Math.max(...arr.map(el => el.map(val => val ? val : 0)).map(el => Math.max(...el)));
|
||||||
|
|
||||||
// Applies the double threshold to the image.
|
// Applies the double threshold to the image.
|
||||||
function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio, grads, strongEdgePixels, weakEdgePixels) {
|
function doubleThreshold(pixels, highThresholdRatio, lowThresholdRatio, grads, strongEdgePixels, weakEdgePixels, pixelsToBeSupressed) {
|
||||||
|
|
||||||
const highThreshold = findMaxInMatrix(grads) * highThresholdRatio, // High Threshold relative to the strongest edge
|
const highThreshold = findMaxInMatrix(grads) * highThresholdRatio, // High Threshold relative to the strongest edge
|
||||||
lowThreshold = highThreshold * lowThresholdRatio; // Low threshold relative to high threshold
|
lowThreshold = highThreshold * lowThresholdRatio; // Low threshold relative to high threshold
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ module.exports = function edgeDetect(options, UI) {
|
|||||||
|
|
||||||
// The function which is called on every draw.
|
// The function which is called on every draw.
|
||||||
function draw(input, callback, progressObj) {
|
function draw(input, callback, progressObj) {
|
||||||
|
|
||||||
progressObj.stop(true);
|
progressObj.stop(true);
|
||||||
progressObj.overrideFlag = true;
|
progressObj.overrideFlag = true;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
35
test/ui-2/test/apply-button.test.js
Normal file
35
test/ui-2/test/apply-button.test.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const timeout = process.env.SLOWMO ? 30000 : 10000;
|
||||||
|
const fs = require('fs');
|
||||||
|
beforeAll(async () => {
|
||||||
|
path = fs.realpathSync('file://../examples/index.html');
|
||||||
|
await page.goto('file://' + path, {waitUntil: 'domcontentloaded'});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Apply Button Works', () => {
|
||||||
|
test('Apply Button is clicked', async () => {
|
||||||
|
await page.waitForSelector('.step');
|
||||||
|
|
||||||
|
|
||||||
|
await page.click('[data-value=\'resize\']');
|
||||||
|
const Length1 = await page.evaluate(() => document.querySelectorAll('.step').length);
|
||||||
|
//Lets change the default value
|
||||||
|
expect(Length1).toBe(2);
|
||||||
|
// Let's check the source of the image output by the default values
|
||||||
|
const src1 = await page.evaluate(() => document.querySelectorAll('.step img')[1].src);
|
||||||
|
//Lets change the default value
|
||||||
|
await page.evaluate(() => document.querySelector('div[name="resize"] input').value = '');
|
||||||
|
await page.type('div[name="resize"] input', '50%');
|
||||||
|
//Wait for the apply button to get enabled then click
|
||||||
|
await page.waitForFunction('document.querySelector(".btn-save").disabled == false');
|
||||||
|
await page.$eval('.btn-save', elem => elem.click());
|
||||||
|
//Wait for the image to process with the new value
|
||||||
|
await page.waitForSelector('.load', {visible: false});
|
||||||
|
|
||||||
|
//Let's check the source of the image output by the new values
|
||||||
|
const src2 = await page.evaluate(() => document.querySelectorAll('.step img')[1].src);
|
||||||
|
//Expect default and new image to be changed
|
||||||
|
expect(src1).not.toEqual(src2);
|
||||||
|
|
||||||
|
|
||||||
|
}, timeout);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user