Compare commits

..

1 Commits

Author SHA1 Message Date
Gaurav Sachdeva
d09231bcef testing 2019-04-01 21:26:38 +05:30
293 changed files with 6594 additions and 13862 deletions

View File

@@ -1,11 +0,0 @@
comment:
layout: "reach, diff, flags, files"
behavior: default
require_changes: false # if true: only post the comment if coverage changes
require_base: no # [yes :: must have a base report to post]
require_head: yes # [yes :: must have a head report to post]
branches: null # branch names that can post comment
coverage:
status:
project: off
patch: off

View File

@@ -1 +0,0 @@
dist/*

View File

@@ -1,36 +0,0 @@
module.exports = {
'env': {
'browser': true,
'commonjs': true,
'es6': true,
'node': true
},
'extends': 'eslint:recommended',
'globals': {
'Atomics': 'readonly',
'SharedArrayBuffer': 'readonly'
},
'parserOptions': {
'ecmaVersion': 2018
},
'rules': {
'indent': ['error',2],
'linebreak-style': ['error','unix'],
'quotes': ['error','single'],
'semi': ['error','always'], //
'no-undef': 0,
'no-console': 'off',
'no-unused-vars': 'off',
'no-redeclare': 'off',
'no-inner-declarations':'off',
'no-empty':'off',
'no-mixed-spaces-and-tabs':'off',
'no-self-assign':'off',
'no-constant-condition':'off',
'no-dupe-keys':'off',
'space-infix-ops': ['error', {'int32Hint': false}], // Enforce spaces around operators
'comma-spacing': ['error', { "before": false, "after": true }], // require spacing after a comma
'comma-style': ['error', 'last'], // requires comma after and on the same line
'no-trailing-spaces': ['error', { 'skipBlankLines': true }], // Disallows trailing whitespace on end of lines and empty lines
}
};

View File

@@ -1,4 +1,4 @@
Fixes #0000 (<=== Replace `0000` with the Issue Number)
Fixes #[Add issue number here.]
Make sure these boxes are checked before your pull request (PR) is ready to be reviewed and merged. Thanks!

View File

@@ -1,12 +0,0 @@
# You can change the labels to suit your needs if "first-timers-only" is not what you are looking for.
# These are some examples.
labels:
- first-timers-only
- help wanted
#If you would like to add your own template for the issue, add an .md file to your .github folder
template: .github/fto-template.md
# You can create the issue in a different repo than where the problem is. Just make sure you installed the bot on the configured repository.
# The issue will link back to the original repository where the contribution will be made.
#repository: repo-name

View File

@@ -1,51 +0,0 @@
Hi, this is a [first-timers-only issue](https://code.publiclab.org/#r=all). This means we've worked to make it more legible to folks who either **haven't contributed to our codebase before, or even folks who haven't contributed to open source before**.
If that's you, we're interested in helping you take the first step and can answer questions and help you out as you do. Note that we're especially interested in contributions from people from groups underrepresented in free and open source software!
We know that the process of creating a pull request is the biggest barrier for new contributors. This issue is for you 💝
If you have contributed before, **consider leaving this one for someone new**, and looking through our general [help wanted](https://github.com/publiclab/image-sequencer/labels/help-wanted) issues. Thanks!
### 🤔 What you will need to know.
Nothing. This issue is meant to welcome you to Open Source :) We are happy to walk you through the process.
### 📋 Step by Step
- [ ] 🙋 **Claim this issue**: Comment below. If someone else has claimed it, ask if they've opened a pull request already and if they're stuck -- maybe you can help them solve a problem or move it along!
- [ ] 📝 **Update** the file [$FILENAME]($BRANCH_URL) in the `$REPO` repository (press the little pen Icon) and edit the line as shown below.
[See this page](https://code.publiclab.org/#r=all) for some help in taking your first steps!
Below is a "diff" showing in red (and a `-`) which lines to remove, and in green (and a `+`) which lines to add:
```diff
$DIFF
```
- [ ] 💾 **Commit** your changes
- [ ] 🔀 **Start a Pull Request**. There are two ways how you can start a pull request:
1. If you are familiar with the terminal or would like to learn it, [here is a great tutorial](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) on how to send a pull request using the terminal.
2. You can also [edit files directly in your browser](https://help.github.com/articles/editing-files-in-your-repository/) and open a pull request from there.
- [ ] 🏁 **Done** Ask in comments for a review :)
### Please keep us updated
💬⏰ - We encourage contributors to be respectful to the community and provide an update **within a week** of claiming a first-timers-only issue. We're happy to keep it assigned to you as long as you need if you update us with a request for more time or help, but if we don't see any activity a week after you claim it we may reassign it to give someone else a chance. Thank you in advance!
If this happens to you, don't sweat it! Grab another open issue.
### Is someone else already working on this?
🔗- We encourage contributors to link to the original issue in their pull request so all users can easily see if someone's already started on it.
👥- **If someone seems stuck, offer them some help!** Otherwise, [take a look at some other issues you can help with](https://code.publiclab.org/#r=all). Thanks!
### 🤔❓ Questions?
Leave a comment below!

View File

@@ -1,12 +1,13 @@
sudo: required
language: node_js
node_js:
- '6'
- '8'
- '10'
env:
- CXX=g++-4.8
before_script:
- npm install grunt-cli -g # for "grunt build"
- npm install jasmine -g
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build
@@ -14,8 +15,6 @@ script:
- npm test
- npm run test-ui
- grunt build
after_success:
- bash <(curl -s https://codecov.io/bash)
after_script:
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
addons:
@@ -25,10 +24,6 @@ addons:
packages:
- g++-4.8
- xvfb # for tape-run
before_install:
- sudo apt-get update
- sudo apt-get install xserver-xorg-dev libxext-dev libxi-dev
- sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config libglu1-mesa-dev freeglut3-dev mesa-common-dev
install:
- export DISPLAY=':99.0' # for tape-run
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & # for tape-run

View File

@@ -3,10 +3,6 @@ Contributing to Image Sequencer
Happily accepting pull requests; to edit the core library, modify files in `./src/`. To build, run `npm install` followed by `grunt build`.
On ARM based devices, the `gl` module may require some libraries to be re-installed:
`sudo apt-get install -y build-essential libxi-dev libglu1-mesa-dev libglew-dev pkg-config` -- see https://github.com/stackgl/headless-gl#ubuntudebian for more.
Most contribution (we imagine) would be in the form of API-compatible modules, which need not be directly included.
## Jump To
@@ -16,7 +12,6 @@ Most contribution (we imagine) would be in the form of API-compatible modules, w
* [Info File](#info-file)
* [Ideas](#Contribution-ideas)
* [Grunt Tasks](#grunt-tasks)
* [UI Helper Methods](#ui-helper-methods)
****
@@ -116,20 +111,7 @@ function ModuleName(options,UI) {
// load a standard info.json file.
];
```
### Running a browser-only module in node
If your module has browser specific code or you are consuming a dependency which does the `gl-context` api. We designed this api especially for webl based modules but since it runs the module in a headless browser, ti supports all browser specific APIs.
The api must be used in the following format
```js
var step = this;
if (!options.inBrowser) {
require('../_nomodule/gl-context')(input, callback, step, options);
}
else {
/* Browser specific code */
}
```
### options
@@ -280,7 +262,6 @@ module.exports = function ModuleName(options,UI) {
The `progressObj` parameter of `draw()` is not consumed unless a custom progress bar needs to be drawn, for which this default spinner should be stopped with `progressObj.stop()` and image-sequencer is informed about the custom progress bar with `progressObj.overrideFlag = true;` following which this object can be overriden with custom progress object.
### Module example
See existing module `channel` for an example: https://github.com/publiclab/image-sequencer/blob/main/src/modules/Channel/Module.js
@@ -369,29 +350,7 @@ module.exports =
});
```
## Linting
We are now using `eslint` and `husky` to help lint and format our code each time we commit. Eslint defines coding standards and helps in cleaning up the code. To run eslint for checking errors globally or within a specific file run:
```
npx eslint .
npx eslint <file path>
```
And to fix those errors globally or in a file, run these in your terminal:
```
npx eslint . --fix
npx eslint <file path> --fix
```
Be sure to not include the angular brackets(<>).
Husky ensures automation of the above steps with git-hooks(eg. git add,git commit..). However we don't want to check and fix changes of the entire codebase with each commit and that the fixes made by eslint appear unstaged and require us to commit them again and that is where lint-staged helps.
If we want `husky` to not verify the commit and push it anyway, use `git commit -m "message" --no-verify.`
## Grunt Tasks
This repository has different grunt tasks for different uses. The source code is in the [Gruntfile](https://github.com/publiclab/image-sequencer/blob/main/Gruntfile.js).
The following command is used for running the tasks: `grunt [task-name]`. Here `[task-name]` should be replaced by the name of the task to be run. To run the default task run `grunt` without any options.
@@ -403,58 +362,3 @@ The following command is used for running the tasks: `grunt [task-name]`. Here `
4. **serve**: Compiles the dist files as in the **compile** task and starts a local server on `localhost:3000` to host the demo site in `/examples/` directory. Also runs the **watch** task.
5. **production**: Compiles and minifies dist files in `/dist/image-sequencer.js` and `/dist/image-sequencer-ui.js` without the `.min.js` extension to include minified files in the demo site. This script should only be used in production mode while deploying.
6. **default**: Runs the **watch** task as default.
## UI Helper Methods
### scopeQuery
###### Path: `/examples/lib/scopeQuery.js`
The method returns a scoped `jQuery` object which only searches for elements inside a given scope (a DOM element).
To use the method,
* import the `scopeSelector` and `scopeSelectorAll` methods from `lib/scopeQuery.js`
* call the methods with scope as a parameter
```js
var scopeQuery = require('./scopeQuery');
var $step = scopeQuery.scopeSelector(scope),
$stepAll = scopeQuery.scopeSelectorAll(scope);
```
This will return an object with a constructor which returns a `jQuery` object (from inside the scope) but with new `elem` and `elemAll` methods.
#### Methods of the Returned Object
* `elem()`: Selects an element inside the scope.
* `elemAll()`: Selects all the instances of a given element inside the scope.
* `getScope()`: Returns the scope as a DOM element.
* `getDomElem()`: Returns the scoped element as a DOM element instead of a jquery object.
#### Example
```js
//The scope is a div element with id=“container“ and there are three divs in it
//with ids „1“, „2“, and „3“, and all of them have a „child“ class attribute
var $step = require('./scopeQuery').scopeSelector(document.getElementById('container'));
$step('#1'); // returns the div element with id=“1“
$step('#1').hide().elemAll('.child').fadeOut(); // abruptly hides the div element with id=“1“ and fades out all other div elements
```
These two methods are chainable and will always return elements from inside the scope.
#### Usage
Instead of using
```js
$(step.ui.querySelector('query')).show().hide();
$(step.ui.querySelectorAll('q2')).show().hide();
```
The following code can be used
```js
$step('query').show().hide();
$stepAll('q2').show().hide();
```

View File

@@ -1,76 +1,76 @@
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify-es');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.loadNpmTasks("grunt-browserify");
grunt.loadNpmTasks("grunt-contrib-uglify-es");
grunt.loadNpmTasks("grunt-browser-sync");
require('matchdep')
.filterDev('grunt-*')
require("matchdep")
.filterDev("grunt-*")
.forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
pkg: grunt.file.readJSON("package.json"),
watch: {
options: {
livereload: true
},
source: {
files: ['src/**/*', 'Gruntfile.js', 'examples/lib/*', 'examples/demo.js'],
tasks: ['compile']
files: ["src/**/*", "Gruntfile.js", "examples/lib/*","examples/demo.js"],
tasks: ["compile"]
}
},
browserify: {
core: {
src: ['src/ImageSequencer.js'],
dest: 'dist/image-sequencer.js'
},
src: ["src/ImageSequencer.js"],
dest: "dist/image-sequencer.js"
},
ui: {
src: ['examples/demo.js'],
dest: 'dist/image-sequencer-ui.js'
src: ["examples/demo.js"],
dest: "dist/image-sequencer-ui.js"
},
prodcore: {
src: ['src/ImageSequencer.js'],
dest: 'dist/image-sequencer.brow.js'
src: ["src/ImageSequencer.js"],
dest: "dist/image-sequencer.brow.js"
},
produi: {
src: ['examples/demo.js'],
dest: 'dist/image-sequencer-ui.brow.js'
src: ["examples/demo.js"],
dest: "dist/image-sequencer-ui.brow.js"
}
},
uglify: {
core: {
src: ['./dist/image-sequencer.js'],
dest: './dist/image-sequencer.min.js'
src: ["./dist/image-sequencer.js"],
dest: "./dist/image-sequencer.min.js"
},
ui: {
src: ['dist/image-sequencer-ui.js'],
dest: 'dist/image-sequencer-ui.min.js'
},
prodcore: {
src: ['dist/image-sequencer.brow.js'],
dest: 'dist/image-sequencer.js'
src: ["dist/image-sequencer.brow.js"],
dest: "dist/image-sequencer.js"
},
produi: {
src: ['dist/image-sequencer-ui.brow.js'],
dest: 'dist/image-sequencer-ui.js'
src: ["dist/image-sequencer-ui.brow.js"],
dest: "dist/image-sequencer-ui.js"
}
},
browserSync: {
dev: {
options: {
watchTask: true,
server: './'
server: "./"
}
}
}
});
/* Default (development): Watch files and build on change. */
grunt.registerTask('default', ['watch']);
grunt.registerTask('build', ['browserify:core', 'browserify:ui', 'uglify:core', 'uglify:ui']);
grunt.registerTask('serve', ['browserify:core', 'browserify:ui', 'browserSync', 'watch']);
grunt.registerTask('compile', ['browserify:core', 'browserify:ui']);
grunt.registerTask('production', ['browserify:prodcore', 'browserify:produi', 'uglify:prodcore', 'uglify:produi']);
grunt.registerTask("default", ["watch"]);
grunt.registerTask("build", ["browserify:core", "browserify:ui", "uglify:core", "uglify:ui"]);
grunt.registerTask("serve", ["browserify:core", "browserify:ui", "browserSync", "watch"]);
grunt.registerTask("compile", ["browserify:core", "browserify:ui"]);
grunt.registerTask("production", ["browserify:prodcore", "browserify:produi", "uglify:prodcore", "uglify:produi"]);
};

View File

@@ -2,7 +2,7 @@ Image Sequencer
====
[![Build Status](https://travis-ci.org/publiclab/image-sequencer.svg?branch=master)](https://travis-ci.org/publiclab/image-sequencer) [![Maintainability](https://api.codeclimate.com/v1/badges/5906996dd2e90aca6398/maintainability)](https://codeclimate.com/github/publiclab/image-sequencer/maintainability) [![Codecov](https://img.shields.io/codecov/c/github/publiclab/image-sequencer.svg?logo=codecov)](https://codecov.io/gh/publiclab/image-sequencer)
[![Build Status](https://travis-ci.org/publiclab/image-sequencer.svg?branch=master)](https://travis-ci.org/publiclab/image-sequencer)
- **Latest Stable Demo**: https://sequencer.publiclab.org
- **Latest Beta Demo**: https://beta.sequencer.publiclab.org
@@ -59,7 +59,7 @@ A diagram of this running 5 steps on a single sample image may help explain how
This library conveniently works in the browser, in Node, and on the command line (CLI).
### Unix based platforms
You can set up a local environment to test the UI with `sudo npm run setup` followed by `npm start`.
You can set up a local environment to test the UI with `npm run setup` followed by `npm start`.
### Windows
Our npm scripts do not support windows shells, please run the following snippet in PowerShell.
@@ -95,7 +95,7 @@ $ npm install image-sequencer -g
```
$ npm run debug invert
```
## Quick Usage
### Initializing the Sequencer
@@ -115,7 +115,7 @@ Note: Browser CORS Restrictions apply. Some browsers may not allow local images
from other folders, and throw a Security Error instead.
```js
sequencer.replaceImage(selector,steps,optional_options);
sequencer.replaceImage(selector,steps,optional_options);
```
`optional_options` allows passing additional arguments to the module itself.
@@ -123,8 +123,8 @@ sequencer.replaceImage(selector,steps,optional_options);
For example:
```js
sequencer.replaceImage('#photo','invert');
sequencer.replaceImage('#photo',['invert','ndvi-red']);
sequencer.replaceImage('#photo','invert');
sequencer.replaceImage('#photo',['invert','ndvi-red']);
```
### Data URL usage
@@ -150,7 +150,7 @@ Image Sequencer also provides a CLI for applying operations to local files. The
The basic format for using the CLI is as follows:
```
$ ./index.js -i [PATH] -s step-name
$ ./index.js -i [PATH] -s step-name
```
*NOTE:* On Windows you'll have to use `node index.js` instead of `./index.js`.
@@ -158,7 +158,7 @@ $ ./index.js -i [PATH] -s step-name
The CLI also can take multiple steps at once, like so:
```
$ ./index.js -i [PATH] -s "step-name-1 step-name-2 ..."
$ ./index.js -i [PATH] -s "step-name-1 step-name-2 ..."
```
But for this, double quotes must wrap the space-separated steps.
@@ -201,17 +201,15 @@ var sequencer = ImageSequencer();
### Loading an Image into the Sequencer
The `loadImage` method is used to load an image into the sequencer. It accepts
an image `src`, either a URL or a data-url. The method also accepts an optional callback.
a name and an image. The method also accepts an optional callback.
```js
sequencer.loadImage(image_src, optional_callback);
sequencer.loadImage(image_src,optional_callback);
```
On `Node.js` the `image_src` may be a DataURI or a local path or a URL.
On browsers, it may be a DatURI, a local image or a URL (Unless this violates
CORS Restrictions). To sum up, these are accepted:
* Images in the same domain (or directory - for a local implementation)
* CORS-Proof images in another domain.
* DataURLs
@@ -221,7 +219,7 @@ The callback is called within the scope of a sequencer. For example:
(addSteps is defined later)
```js
sequencer.loadImage('SRC', function(){
sequencer.loadImage('SRC',function(){
this.addSteps('module-name');
});
```
@@ -243,39 +241,7 @@ If multiple images are to be added, `modules` is an array, which holds the names
to be added, in that particular order.
optional_otions is just an optional parameter, in object form, which you might
want to provide to the modules.
A variety of syntaxes are supported by Image Sequencer to add multiple steps and configurations quickly for module chaining. The project supports the string syntax, designed to be compact and URL friendly, and JSON, for handling more complex sequences. This can be achieved by passing strings to `sequencer.addStep()`:
```js
sequencer.addSteps('invert,channel');
sequencer.addSteps(['invert','channel']);
```
For passing default configurations ({} is optional):
```js
sequencer.addSteps('brightness{}');
```
For passing custom configurations:
```js
sequencer.addSteps('brightness{brightness:80}');
```
For passing multiple custom configurations:
```js
sequencer.addSteps('crop{x:120|y:90}')
```
For passing multiple custom configurable modules:
```js
sequencer.addSteps('crop{x:130|y:80},brightness{brightness:80}')
```
want to provide to the modules.
return value: **`sequencer`** (To allow method chaining)
@@ -432,7 +398,7 @@ Image sequencer supports stringifying a sequence which is appended to the url an
channel{channel:green},invert{}
```
The use of `()` in place of `{}` for backward compatibility with older links is now **deprecated**. (There is no longer support for the following syntax, and should be avoided)
Sequencer also supports the use of `()` in place of `{}` for backward compatibility with older links. (This syntax is deprecated and should be avoided as far as possible)
```
channel(channel:green),invert()
```
@@ -471,7 +437,7 @@ sequencer.importJSON([
To see this in action, please refer to line # 51 of the following:
[test/core/modules/import-export.js](https://github.com/publiclab/image-sequencer/blob/main/test/core/modules/import-export.js)
## Creating a User Interface
@@ -548,7 +514,7 @@ sequencer.setUI({
Image Sequencer object supports one imageURL at a time.
Adding a seccond image to same sequencer will result to adding same set of steps added to prior image and flushing out the previous one.
Adding a seccond image to same sequencer will result to adding same set of steps added to prior image and flushing out the previous one.
```js
s1 = new ImageSequencer(...);
@@ -578,24 +544,3 @@ sequencer2.run();
This method returns an object which defines the name and inputs of the modules. If a module name (hyphenated) is passed in the method, then only the details of that module are returned.
The `notify` function takes two parameters `msg` and `id`, former being the message to be displayed on console (in case of CLI and node ) and a HTML component(in browser). The id is optional and is useful for HTML interface to give appropriate IDs.
## Using WebAssembly for heavy pixel processing
Any module which uses the `changePixel` function gets WebAssembly acceleration (`wasm`). Both node and browser code use WebAssembly and the only code which falls back to non-`wasm` code is the [browserified unit tests](https://github.com/publiclab/image-sequencer/blob/main/test/core/sequencer/benchmark.js).
The main advantage we get using `wasm` is blazing fast speed attained in processing pixels for many modules that is very clear from [checking module benchmarks](https://travis-ci.org/publiclab/image-sequencer/jobs/544415673#L1931).
The only limitation is that browser and node code for `wasm` had to be written separately, and switched between. This is because in browser we use `fetch` to retrieve the compiled `wasm` program while in node we use the `fs` module, each of which cannot be used in the other's environment.
`wasm` mode is enabled by default. If you need to force this mode to be on or off, you can use the `useWasm` option when initializing ImageSequencer:
```js
let sequencer = ImageSequencer({useWasm:true}) // for wasm mode or simply
let sequencer = ImageSequencer() // also for wasm mode i.e. default mode
let sequencer = ImageSequencer({useWasm:false}) //for non-wasm mode
```

View File

@@ -36,7 +36,6 @@
"node_shared_libuv": "false",
"node_shared_openssl": "false",
"node_shared_zlib": "false",
"node_tag": "",
"node_use_bundled_v8": "true",
"node_use_dtrace": "true",
"node_use_etw": "false",

BIN
dist/manipulation.wasm vendored

Binary file not shown.

View File

@@ -3,229 +3,47 @@ Documentation of various Modules
List of Module Documentations
1. [Add QR](#Add-QR-module)
2. [Average](#average-module)
3. [Blend](#blend-module)
4. [Blur](#blur-module)
5. [Brightness](#brightness-module)
6. [Channel](#channel-module)
7. [Colorbar](#colorbar-module)
8. [Colormap](#colormap-module)
9. [ColorTemperature](#color-temperature)
10. [Contrast](#contrast-module)
11. [Convolution](#convolution-module)
12. [Crop](#crop-module)
13. [DecodeQr](#decodeQr-module)
14. [Dither](#dither-module)
15. [DrawRectangle](#draw-rectangle-module)
16. [Dynamic](#dynamic-module)
17. [Edge-Detect](#edge-detect-module)
18. [FisheyeGl](#fisheyeGl-module)
1. [Crop](#crop-module)
2. [Segmented-Colormap](#segmented-colormap-module)
3. [FisheyeGl](#fisheyeGl-module)
4. [Add QR](#Add-QR-module)
5. [Average](#average-module)
6. [Blend](#blend-module)
7. [Blur](#blur-module)
8. [Brightness](#brightness-module)
9. [Channel](#channel-module)
10. [Colorbar](#colorbar-module)
11. [Colormap](#colormap-module)
12. [Contrast](#contrast-module)
13. [Convolution](#convolution-module)
14. [DecodeQr](#decodeQr-module)
15. [Dither](#dither-module)
16. [DrawRectangle](#draw-rectangle-module)
17. [Dynamic](#dynamic-module)
18. [Edge-Detect](#edge-detect-module)
19. [FlipImage](#flipimage-module)
20. [Gamma-Correction](#gamma-correction-module)
21. [Gradient](#gradient-module)
22. [Grid-Overlay](#grid-overlay)
23. [Histogram](#histogram-module)
24. [Import-image](#import-image-module)
25. [Invert](#invert-module)
26. [MinifyImage](#minify-image)
27. [Ndvi](#ndvi-module)
28. [Ndvi-Colormap](#ndvi-colormap-module)
29. [Overlay](#overlay-module)
30. [PaintBucket](#paint-bucket-module)
31. [ReplaceColor](#replacecolor-module)
32. [Resize](#resize-module)
33. [Rotate](#rotate-module)
34. [Saturation](#saturation-module)
35. [Segmented-Colormap](#segmented-colormap-module)
36. [Text-Overlay](#text-overlay)
37. [Threshold](#threshold)
38. [Tint](#tint)
## add-qr-module
This module Adds QR corresponding to the given string.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('add-qr',options)
.run()
```
where `options` is an object with the following properties:
* size : size of QR code in pixels (default 200)
* qrCodeString : input string to generate QR code
## average-module
This module is used for averaging all the pixels of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('average',options)
.run()
```
## blend-module
This module is used for blending two images .
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blend',options)
.run()
```
where `options` is an object with the following properties:
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
## Blob Analysis
This module uses Opencv.js for detecting and marking blob/region in microscopic images. It requires an opencv.js file to
be loaded before using the functionalities which is currently being loaded to the webpage via script.It supports both environments, Node.js and browser for processing.
As the size of opencv.js file is quite large, the future versions will focus on loading it asynchronously, on demand of the the module to optimise performance.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blob-analysis')
.run()
```
## blur-module
This module is used for applying a Gaussian blur effect.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blur',options)
.run()
```
where `options` is an object with the following property:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
## brightness-module
This module is used for changing the brightness of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('brightness',options)
.run()
```
where `options` is an object with the following property:
* brightness : brightness of the image in percentage (0 to 100; default 100)
## channel-module
This module is used for forming a grayscale image by applying one of the three primary colors.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('channel',options)
.run()
```
where `options` is an object with the following property:
* channel : color of the channel (red, green, blue; default green)
## colorbar-module
This module is used for displaying an image with a colorbar.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colorbar',options)
.run()
```
where `options` is an object with the following properties:
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
* x : X-position of the image on which the new image is overlayed (default 0)
* y : Y-position of the image on which the new image is overlayed (default 0)
* h : height of resulting cropped image (default : 50% of input image width )
## colormap-module
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colormap',options)
.run()
```
where `options` is an object with the following property:
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
## Color Temperature
This changes the color temperature of the image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('color-temperature',options)
.run()
```
where `options` is an object with the following property:
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
## contrast-module
This module is used for changing the contrast of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('contrast',options)
.run()
```
where `options` is an object with the following property:
* contrast : contrast for the given image (-100 to 100; default : 70)
## convolution-module
This module is used for performing image-convolution.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('convolution',options)
.run()
```
where `options` is an object with the following properties:
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
22. [Histogram](#histogram-module)
23. [Import-image](#import-image-module)
24. [Invert](#invert-module)
25. [Ndvi](#ndvi-module)
26. [Ndvi-Colormap](#ndvi-colormap-module)
27. [Overlay](#overlay-module)
28. [PaintBucket](#paint-bucket-module)
29. [Resize](#resize-module)
30. [ReplaceColor](#replacecolor-module)
31. [Rotate](#rotate-module)
32. [Saturation](#saturation-module)
33. [Threshold](#threshold)
34. [Tint](#tint)
35. [ColorTemperature](#color-temperature)
## crop-module
This module is used to crop an image.
#### Usage
```js
@@ -245,90 +63,34 @@ Where `options` is an object having the properties `x`, `y`, `w`, `h`. This diag
* `options.h` : half of image height
## decodeQr-module
## segmented-colormap-module
This module is used to map the pixels of the image to a segmented colormap.
This module is used for decoding a QR in image (if present).
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('decode-qr',options)
.addSteps('segmented-colormap',options)
.run()
```
## dither-module
where `options` is an object with the property `colormap`. `options.colormap` can be:
This module approximates a color from a mixture of other colors when the required color is not available, creating illusions of the color that is not present actually.
* "default" : [[0, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 50, 50]]]
[more info on wikipedia](https://en.wikipedia.org/wiki/Dither)
#### Usage
* "greyscale" : [[0, [0, 0, 0], [255, 255, 255]], [1, [255, 255, 255], [255, 255, 255]]]
```js
sequencer.loadImage('PATH')
.addSteps('dither',options)
.run()
```
where `options` is an object with the following property:
* dither : Can select the name of the Dithering Algorithm(default none)
* "stretched" : [[0, [0, 0, 255], [0, 0, 255]], [0.1, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.7, [255, 255, 0], [255, 50, 50]], [0.9, [255, 50, 50], [255, 50, 50]]]
## draw-rectangle-module
This module helps to draw a rectangle on the image with a starting and ending corner with the specified thickness and color of the border.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('draw-rectangle',options)
.run()
```
where `options` is an object with the following properties:
* startingX : starting x position of the rectangle (default 0)
* startingY : starting y position of the rectangle (default 0)
* endX : last x position of the rectangle (default "width")
* endY : last y position of the rectangle (default "height")
* thickness : thickness of the border (default 1)
* color : RGBA values separated by a space (default "0 0 0 255")
## dynamic-module
This module is used for producing each color channel based on the original image's color.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('dynamic',options)
.run()
```
where `options` is an object with the following properties:
* red : expression for red channel (R, G, B and A as inputs; default r)
* green : expression for green channel (R, G, B and A as inputs; default g)
* blue : expression for blue channel (R, G, B and A as inputs; default b)
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
## edge-detect-module
This module is used for detecting images.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('edge-detect',options)
.run()
```
where `options` is an object with the following properties:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
* "fastie" : [[0, [255, 255, 255], [0, 0, 0]], [0.167, [0, 0, 0], [255, 255, 255]], [0.33, [255, 255, 255], [0, 0, 0]], [0.5, [0, 0, 0], [140, 140, 255]], [0.55, [140, 140, 255], [0, 255, 0]], [0.63, [0, 255, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 0, 0]], [0.95, [255, 0, 0], [255, 0, 255]]]
* A custom array.
## fisheyeGl-module
This module is used for correcting Fisheye or Lens Distortion
#### Usage
```js
@@ -346,12 +108,246 @@ where `options` is an object with the following properties:
* x : Field of View x (0 to 2; default 1)
* y : Field of View y (0 to 2; default 1)
## add-qr-module
This module Adds QR corresponding to the given string.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('add-qr',options)
.run()
```
where `options` is an object with the following properties:
* size : size of QR code in pixels (default 200)
* qrCodeString : input string to generate QR code
## average-module
This module is used for averaging all the pixels of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('average',options)
.run()
```
## blend-module
This module is used for blending two images .
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blend',options)
.run()
```
where `options` is an object with the following properties:
* offset: step of image with which current image is to be blended(Two steps back is -2, three steps back is -3 etc; default -2)
* func: function used to blend two images (default : function(r1, g1, b1, a1, r2, g2, b2, a2) { return [ r1, g2, b2, a2 ] })
## blur-module
This module is used for applying a Gaussian blur effect.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('blur',options)
.run()
```
where `options` is an object with the following property:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
## brightness-module
This module is used for changing the brightness of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('brightness',options)
.run()
```
where `options` is an object with the following property:
* brightness : brightness of the image in percentage (0 to 100; default 100)
## channel-module
This module is used for forming a grayscale image by applying one of the three primary colors.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('channel',options)
.run()
```
where `options` is an object with the following property:
* channel : color of the channel (red, green, blue; default green)
## colorbar-module
This module is used for displaying an image with a colorbar.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colorbar',options)
.run()
```
where `options` is an object with the following properties:
* colormap : Name of the Colormap(default, greyscale, stretched, fastie, brntogrn, blutoredjet, colors16; default: default)
* x : X-position of the image on which the new image is overlayed (default 0)
* y : Y-position of the image on which the new image is overlayed (default 0)
* h : height of resulting cropped image (default : 50% of input image width )
## colormap-module
This module is used for mapping brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('colormap',options)
.run()
```
where `options` is an object with the following property:
* colormap : Name of the Colormap ( greyscale, stretched, fastie, brntogrn, blutoredjet, colors16)
## contrast-module
This module is used for changing the contrast of the image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('contrast',options)
.run()
```
where `options` is an object with the following property:
* contrast : contrast for the given image (-100 to 100; default : 70)
## convolution-module
This module is used for performing image-convolution.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('convolution',options)
.run()
```
where `options` is an object with the following properties:
* constantFactor : a constant factor, multiplies all the kernel values by that factor (default : 1/9)
* kernelValues : nine space separated numbers representing the kernel values in left to right and top to bottom format(default : 1 1 1 1 1 1 1 1 1)
## decodeQr-module
This module is used for decoding a QR in image (if present).
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('decode-qr',options)
.run()
```
## dither-module
This module approximates a color from a mixture of other colors when the required color is not available, creating illusions of the color that is not present actually.
[more info on wikipedia](https://en.wikipedia.org/wiki/Dither)
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('dither',options)
.run()
```
where `options` is an object with the following property:
* dither : Can select the name of the Dithering Algorithm(default none)
## draw-rectangle-module
This module helps to draw a rectangle on the image with a starting and ending corner with the specified thickness and color of the border.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('draw-rectangle',options)
.run()
```
where `options` is an object with the following properties:
* startingX : starting x position of the rectangle (default 0)
* startingY : starting y position of the rectangle (default 0)
* endX : last x position of the rectangle (default "width")
* endY : last y position of the rectangle (default "height")
* thickness : thickness of the border (default 1)
* color : RGBA values separated by a space (default "0 0 0 255")
## dynamic-module
This module is used for producing each color channel based on the original image's color.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('dynamic',options)
.run()
```
where `options` is an object with the following properties:
* red : expression for red channel (R, G, B and A as inputs; default r)
* green : expression for green channel (R, G, B and A as inputs; default g)
* blue : expression for blue channel (R, G, B and A as inputs; default b)
* monochrome: fallback for other channels if none provided (default : r+g+b/3)
## edge-detect-module
This module is used for detecting images.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('edge-detect',options)
.run()
```
where `options` is an object with the following properties:
* blur : Intensity of Gaussian blur (0 to 5; default 2)
* highThresholdRatio : Upper Threshold Ratio ( default : 0.2)
* lowThresholdratio : Lower Threshold Ratio ( default : 0.2)
## flipimage-module
This module is used for flipping the image on the selected axis.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('flip-image',options)
@@ -376,7 +372,6 @@ This module is used for applying gamma correction.
where `options` is an object with the following property:
* adjustment : Inverse of actual gamma factor (default 0.2)
## gradient-module
This module is used for finding gradient of the image.
@@ -388,23 +383,6 @@ This module is used for finding gradient of the image.
.run()
```
## Grid Overlay
This adds the grid over an image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('grid-overlay',options)
.run()
```
where `options` is an object with the following property:
* options.x : The value at which the grid line should start in x-axis.
* options.y : The value at which the grid line should start in y-axis.
* color : Color for the grid on the image.
## histogram-module
This module is used for calculating histogram of the image.
@@ -419,7 +397,6 @@ This module is used for calculating histogram of the image.
where `options` is an object with the following property:
* gradient : boolean value used to toggle gradient along x-axis (true or false; default true)
## import-image-module
This module is used for importing a new image and replacing the original with it.
@@ -434,7 +411,6 @@ This module is used for importing a new image and replacing the original with it
where `options` is an object with the following property:
* url : url of the new image (local image url or data url;default : "./images/monarch.png")
## invert-module
This module is used for inverting the image.
@@ -446,21 +422,6 @@ This module is used for inverting the image.
.run()
```
## Minify Image
This module minifies the image using lossy compression that is the image-dimensions are not lost but the size is reduced.
The module supports jpg/jpeg/webp images in browser; but the node version supports all of the types.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('minify-image')
.run()
```
## ndvi-module
This module is used for applying ndvi technique to the image.
@@ -475,7 +436,6 @@ This module is used for applying ndvi technique to the image.
where `options` is an object with the following property:
* filter : filter for NDVI (blue or red; default red)
## ndvi-colormap-module
This module is used for demonstrating ndvi and colormap properties consecutively.
@@ -487,7 +447,6 @@ This module is used for demonstrating ndvi and colormap properties consecutively
.run()
```
## overlay-module
This module is used for overlaying an Image over another .
@@ -504,10 +463,10 @@ where `options` is an object with the following properties:
* y : Y-position of the image on which the new image is overlayed (default 0)
* offset : offset to the step on which the output of the last step is overlayed (default -2)
## paint-bucket-module
This module fills any polygonal shape with the specified color in pixels.
## Usage
```js
@@ -522,6 +481,19 @@ where `options` is an object with the following property:
* fillColor : they are four spaced seperated numbers representing the RGBA values of fill-color (default "100 100 100 255")
* tolerance : it is the % tolerance (default 10)
## resize-module
This module is used for resizing an image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('resize',options)
.run()
```
where `options` is an object with the following property:
* resize : Percentage value of resize (default 125%)
## replacecolor-module
@@ -539,22 +511,6 @@ where `options` is an object with the following properties:
* color : three space separated numbers representing the RGB values of color to be replaced (default "228 86 81")
* tolerance : it is the % tolerance (default 50)
## resize-module
This module is used for resizing an image.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('resize',options)
.run()
```
where `options` is an object with the following property:
* resize : Percentage value of resize (default 125%)
## rotate-module
This module is used for rotating an image.
@@ -569,7 +525,6 @@ This module is used for rotating an image.
where `options` is an object with the following property:
* rotate : angular value for rotation in degrees (between 0 and 360; default 0)
## saturation-module
This module is used for changing the saturation of the image.
@@ -584,49 +539,11 @@ This module is used for changing the saturation of the image.
where `options` is an object with the following property:
* saturation : saturation for the new image (between 0 and 2; default 0)
## segmented-colormap-module
This module is used to map the pixels of the image to a segmented colormap.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('segmented-colormap',options)
.run()
```
where `options` is an object with the property `colormap`. `options.colormap` can be:
* "default" : [[0, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 50, 50]]]
* "greyscale" : [[0, [0, 0, 0], [255, 255, 255]], [1, [255, 255, 255], [255, 255, 255]]]
* "stretched" : [[0, [0, 0, 255], [0, 0, 255]], [0.1, [0, 0, 255], [38, 195, 195]], [0.5, [0, 150, 0], [255, 255, 0]], [0.7, [255, 255, 0], [255, 50, 50]], [0.9, [255, 50, 50], [255, 50, 50]]]
* "fastie" : [[0, [255, 255, 255], [0, 0, 0]], [0.167, [0, 0, 0], [255, 255, 255]], [0.33, [255, 255, 255], [0, 0, 0]], [0.5, [0, 0, 0], [140, 140, 255]], [0.55, [140, 140, 255], [0, 255, 0]], [0.63, [0, 255, 0], [255, 255, 0]], [0.75, [255, 255, 0], [255, 0, 0]], [0.95, [255, 0, 0], [255, 0, 255]]]
* A custom array.
## Text Overlay
The modules allows to add text to image in both browser and node environment. We have the options to modify the font-size and also support few font-styles. The text color can also be modified.
#### Usage
```js
sequencer.loadImage('PATH')
.addSteps('grid-overlay',options)
.run()
```
The options can take various attributes like,
var options = { text : 'Hello World', size : '12'};
## Threshold
Thresholding is used to create binary images.
#### Usage
## Usage
```js
sequencer.loadImage('PATH')
@@ -641,7 +558,8 @@ where `options` is an object with the following property:
## Tint
It adds color tint to an image
#### Usage
## Usage
```js
sequencer.loadImage('PATH')
@@ -651,3 +569,19 @@ It adds color tint to an image
where `options` is an object with the following property:
* color : RGB values seperated by a space (default "0 0 255")
* factor : amount of tint (default 0.5)
## Color Temperature
This changes the color temperature of the image.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('color-temperature',options)
.run()
```
where `options` is an object with the following property:
* temperature : temperature between 0 - 40,000 kelvin (default 6000)

View File

@@ -252,27 +252,3 @@ a.name-header{
.trash-container button.btn-xs {
margin-top: -5px !important;
}
.toggleIcon {
transition: transform 0.2s;
}
.rotated {
transform: rotate(180deg);
}
#gif{
margin-left:0px;
margin-top:5px;
width:100%;
}
.save-button{
margin-top:20px;
margin-bottom:0px;
align:center;
width:100%;
}
.toggle {
cursor: default;
}

View File

@@ -1,32 +1,32 @@
var defaultHtmlSequencerUi = require('./lib/defaultHtmlSequencerUi.js'),
setupCache = require('./lib/cache.js'),
intermediateHtmlStepUi = require('./lib/intermediateHtmlStepUi.js'),
DefaultHtmlStepUi = require('./lib/defaultHtmlStepUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js');
setupCache = require('./lib/cache.js'),
intermediateHtmlStepUi = require('./lib/intermediateHtmlStepUi.js'),
DefaultHtmlStepUi = require('./lib/defaultHtmlStepUi.js'),
urlHash = require('./lib/urlHash.js'),
insertPreview = require('./lib/insertPreview.js');
window.onload = function () {
window.onload = function() {
sequencer = ImageSequencer();
function refreshOptions() {
// Load information of all modules (Name, Inputs, Outputs)
var modulesInfo = sequencer.modulesInfo();
var addStepSelect = $('#addStep select');
addStepSelect.html('');
var addStepSelect = $("#addStep select");
addStepSelect.html("");
// Add modules to the addStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] && modulesInfo[m].name)
addStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
);
}
// Null option
addStepSelect.append('<option value="" disabled selected>Select a Module</option>');
addStepSelect.append('<option value="none" disabled selected>More modules...</option>');
addStepSelect.selectize({
sortField: 'text'
});
});
}
refreshOptions();
@@ -36,7 +36,7 @@ window.onload = function () {
var shouldDisplay = $('body').scrollTop() > 20 || $(':root').scrollTop() > 20;
$('#move-up').css({
display: shouldDisplay ? 'block' : 'none'
display: shouldDisplay ? 'block' : 'none'
});
}
@@ -46,7 +46,7 @@ window.onload = function () {
$(':root').animate({scrollTop: 0});
}
$('#move-up').on('click', topFunction);
$('#move-up').on("click",topFunction);
// UI for each step:
@@ -59,100 +59,105 @@ window.onload = function () {
if (urlHash.getUrlHashParameter('src')) {
sequencer.loadImage(urlHash.getUrlHashParameter('src'), ui.onLoad);
} else {
sequencer.loadImage('images/tulips.png', ui.onLoad);
sequencer.loadImage("images/tulips.png", ui.onLoad);
}
var resetSequence = function () {
var r = confirm('Do you want to reset the sequence?');
var resetSequence = function(){
var r=confirm("Do you want to reset the sequence?");
if (r)
window.location = '/';
};
window.location = "/";
}
$('#addStep select').on('change', ui.selectNewStepUi);
$('#addStep #add-step-btn').on('click', ui.addStepUi);
$('#resetButton').on('click', resetSequence);
$("#addStep select").on("change", ui.selectNewStepUi);
$("#addStep #add-step-btn").on("click", ui.addStepUi);
$("#resetButton").on("click",resetSequence);
//Module button radio selection
$('.radio-group .radio').on('click', function () {
$('.radio-group .radio').on("click", function() {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
//$("#addStep option[value=" + newStep + "]").attr('selected', 'selected');
$('#addStep select').val(newStep);
$("#addStep select").val(newStep);
ui.selectNewStepUi(newStep);
ui.addStepUi(newStep);
$(this).removeClass('selected');
});
function displayMessageOnSaveSequence() {
$('.savesequencemsg').fadeIn();
setTimeout(function () {
$('.savesequencemsg').fadeOut();
}, 3000);
}
$('#download-btn').click(function() {
$('.step-thumbnail:last()').trigger("click");
return false;
});
function displayMessageOnSaveSequence(){
$(".savesequencemsg").fadeIn();
setTimeout(function() {
$(".savesequencemsg").fadeOut();
}, 1000);
}
$('body').on('click', 'button.remove', ui.removeStepUi);
function saveSequence() { // 1. save seq
var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).');
if (result) {
result = result + ' (local)';
sequencer.saveSequence(result, sequencer.toString()); // 1.a study saveSequence
$('#save-seq').click(() => {
var result = window.prompt("Please give a name to your sequence... (Saved sequence will only be available in this browser).");
if(result){
result = result + " (local)";
sequencer.saveSequence(result, sequencer.toString());
sequencer.loadModules();
displayMessageOnSaveSequence();
refreshOptions();
}
}
$('#saveButton').on('click', function () {
// different handlers triggered for different dropdown options
let dropDownValue = $('#selectSaveOption option:selected').val();
if (dropDownValue == 'save-image') {
$('.download-btn:last()').trigger('click');
}
else if (dropDownValue == 'save-gif') {
handleSavePNG();
}
else if (dropDownValue == 'save-seq') {
saveSequence();
}
});
let isWorkingOnGifGeneration = false;
var isWorkingOnGifGeneration = false;
$('.js-view-as-gif').on('click', function (event) {
/* Prevent user from triggering generation multiple times*/
$('.js-view-as-gif').on('click', function(event) {
// Prevent user from triggering generation multiple times
if (isWorkingOnGifGeneration) return;
isWorkingOnGifGeneration = true;
var button = event.target;
button.disabled = true;
button.innerHTML = '<i class="fa fa-circle-o-notch fa-spin"></i>';
try {
/* Get gif resources of previous steps */
let options = getGifResources();
// Select all images from previous steps
var imgs = document.getElementsByClassName("step-thumbnail");
gifshot.createGIF(options, function (obj) { // gif generation
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = {
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
}
gifshot.createGIF(options, function(obj) {
if (!obj.error) {
// Final gif encoded with base64 format
var image = obj.image;
var animatedImage = document.createElement('img');
animatedImage.id = 'gif_element';
animatedImage.id = "gif_element";
animatedImage.src = image;
let modal = $('#js-download-gif-modal');
$('#js-download-as-gif-button').one('click', function () {
var modal = $('#js-download-gif-modal');
$("#js-download-as-gif-button").one("click", function() {
// Trigger download
downloadGif(image);
download(image, "index.gif", "image/gif");
// Close modal
modal.modal('hide');
});
})
var gifContainer = document.getElementById('js-download-modal-gif-container');
var gifContainer = document.getElementById("js-download-modal-gif-container");
// Clear previous results
gifContainer.innerHTML = '';
@@ -165,7 +170,6 @@ window.onload = function () {
modal.modal();
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
});
@@ -173,80 +177,47 @@ window.onload = function () {
catch (e) {
console.error(e);
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
});
function getGifResources() {
/* Returns an object with specific gif options */
let imgs = document.getElementsByClassName('step-thumbnail');
var imgSrcs = [];
// Pushes image sources of all the modules in dom
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
var options = { // gif frame options
'gifWidth': imgs[0].width,
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
};
return options;
}
function handleSavePNG() {
let options = getGifResources();
gifshot.createGIF(options, function(obj){
downloadGif(obj.image);
});
}
function downloadGif(image) {
download(image, 'index.gif', 'image/gif');// downloadjs library function
}
// image selection and drag/drop handling from examples/lib/imageSelection.js
sequencer.setInputStep({
dropZoneSelector: '#dropzone',
fileInputSelector: '#fileInput',
takePhotoSelector: '#take-photo',
dropZoneSelector: "#dropzone",
fileInputSelector: "#fileInput",
takePhotoSelector: "#take-photo",
onLoad: function onFileReaderLoad(progress) {
var reader = progress.target;
var step = sequencer.steps[0];
var util = intermediateHtmlStepUi(sequencer);
var util= intermediateHtmlStepUi(sequencer);
step.output.src = reader.result;
sequencer.run({ index: 0 });
if (typeof step.options !== 'undefined')
if(typeof step.options !=="undefined")
step.options.step.imgElement.src = reader.result;
else
step.imgElement.src = reader.result;
insertPreview.updatePreviews(reader.result, '#addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src, '.insertDiv');
insertPreview.updatePreviews(reader.result,'addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src,'insertStep');
},
onTakePhoto: function (url) {
var step = sequencer.steps[0];
step.output.src = url;
sequencer.run({ index: 0 });
if (typeof step.options !== 'undefined')
if(typeof step.options !=="undefined")
step.options.step.imgElement.src = url;
else
step.imgElement.src = url;
insertPreview.updatePreviews(url, '#addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src, '.insertDiv');
insertPreview.updatePreviews(url,'addStep');
insertPreview.updatePreviews(sequencer.steps[0].imgElement.src,'insertStep');
}
});
setupCache();
if (urlHash.getUrlHashParameter('src')) {
insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'), '#addStep');
insertPreview.updatePreviews(urlHash.getUrlHashParameter('src'),'addStep');
} else {
insertPreview.updatePreviews('images/tulips.png', '#addStep');
insertPreview.updatePreviews("images/tulips.png",'addStep');
}
};
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -9,16 +9,11 @@
<meta name="theme-color" content="#428bca">
<link rel="icon" sizes="192x192" href="../icons/ic_192.png">
<link rel="manifest" href="manifest.json">
<!--Adding meta Tag for search engine optimisation-->
<meta property="og:description"
content="A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it creates a new image at each step in a sequence.">
<meta property="og:site_name" content="sequencer.publiclab.org">
<meta property="og:url" content="https://sequencer.publiclab.org">
<meta property="og:title" content="Image Sequencer">
<meta name="Description"
content="Image Sequencer is an image editing tool that creates a new downloadble image at each step.It works in browser and supports both node and CLI.">
<meta name="Keywords" content="image editing downloadable browser node CLI">
<!--Adding meta Tag for search engine optimisation-->
<meta property="og:description" content="A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it creates a new image at each step in a sequence.">
<meta property="og:site_name" content="sequencer.publiclab.org">
<meta property="og:url" content="https://sequencer.publiclab.org">
<meta property="og:title" content="Image Sequencer">
<title>Image Sequencer</title>
@@ -27,13 +22,12 @@
<script src="../src/ui/prepareDynamic.js"></script>
<script src="../dist/image-sequencer.js" charset="utf-8"></script>
<script src="../dist/image-sequencer-ui.js" charset="utf-8"></script>
<script src="../node_modules/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js"></script>
<!-- for crop module: -->
<script src="../node_modules/imgareaselect/jquery.imgareaselect.dev.js"></script>
<script src="../node_modules/gifshot/dist/gifshot.min.js" type="text/javascript"></script>
<!-- Download.js for large files -->
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript" />
<script src="../node_modules/downloadjs/download.min.js" type="text/javascript"/>
<script src="lib/scrollToTop.js"></script>
<script src="../node_modules/selectize/dist/js/standalone/selectize.min.js"></script>
@@ -42,14 +36,10 @@
<body>
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../node_modules/bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css" rel="stylesheet">
<link rel="stylesheet" href="demo.css">
<link href="../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="../node_modules/selectize/dist/css/selectize.default.css" rel="stylesheet">
<!-- for crop module: -->
<!-- for crop module: -->
<link href="../node_modules/imgareaselect/distfiles/css/imgareaselect-default.css" rel="stylesheet">
<link href="./selectize.default.css" rel="stylesheet">
<link rel="stylesheet" href="demo.css">
@@ -58,8 +48,7 @@
<header class="text-center">
<h1><a href="/" target='_blank' class="name-header">Image Sequencer</a></h1>
<p>
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original
image, it
A pure JavaScript sequential image processing system, inspired by storyboards. Instead of modifying the original image, it
creates a new image at each step in a sequence.
<a href="https://publiclab.org/image-sequencer">Learn more</a>
</p>
@@ -68,7 +57,7 @@
<a href="https://github.com/publiclab/image-sequencer">
<i class="fa fa-github"></i>
</a>
by <a href="https://publiclab.org" title="Publiclab Website"><i class="fa fa-globe"></i> Publiclab</a>
by <a href= "https://publiclab.org" title = "Publiclab Website"><i class = "fa fa-globe"></i> Publiclab</a>
</p>
</header>
@@ -79,7 +68,7 @@
<center>
<input type="file" id="fileInput" value="" accept="image/*"><br />
<button type="button" id="take-photo" class="btn btn-primary btn-block btn-lg ">Take a Photo</button>
<video id="video" width="100%" height="100%" style="display:none"></video>
<video id="video" width="400" height="300" style="display:none"></video>
<a href="#" id="capture" style="display:none" class="btn btn-primary btn-md">Click Picture</a>
<a href="#" id="close" style="display:none" class="btn btn-default btn-md">Close</a>
<canvas id="canvas" width="400" height="300" style="display:none"></canvas>
@@ -91,79 +80,79 @@
</section>
<hr />
<p class="alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules in browser's localStorage.
</p>
<div class="row">
<div class="col-sm-8">
<section id="addStep" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="display:flex; justify-content:center;">
<p class = "alert alert-success savesequencemsg">Saved Sequence Success. Sequence can be found among other modules.</p>
<div class="row">
<div class="col-sm-8">
<section id="addStep" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="display:flex; justify-content:center;">
</div>
<p class="info">Select a new module to add to your sequence.</p>
<div class="row center-align radio-group">
<div>
<div class="radio" data-value="resize">
<i class="fa fa-arrows-alt fa-4x i-over"></i>
</div>
<p class="info">Select a new module to add to your sequence.</p>
<div class="row center-align radio-group">
<div>
<div class="radio" data-value="resize">
<i class="fa fa-arrows-alt fa-4x i-over"></i>
</div>
<p>Resize</p>
</div>
<div>
<div class="radio" data-value="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
</div>
<p>Brightness</p>
</div>
<div>
<div class="radio" data-value="contrast">
<i class="fa fa-adjust fa-4x i-over"></i>
</div>
<p>Contrast</p>
</div>
<div>
<div class="radio" data-value="saturation">
<i class="fa fa-tint fa-4x i-over i-small"></i>
</div>
<p>Saturation</p>
</div>
<div>
<div class="radio" data-value="rotate">
<i class="fa fa-rotate-right fa-4x i-over"></i>
</div>
<p>Rotate</p>
</div>
<div>
<div class="radio" data-value="crop">
<i class="fa fa-crop fa-4x i-over"></i>
</div>
<p>Crop</p>
</div>
<p>Resize</p>
</div>
<div>
<div class="radio" data-value="brightness">
<i class="fa fa-sun-o fa-4x i-over"></i>
</div>
<div class="row center-align">
<div class="col-md-8">
<select id="selectStep">
<!-- The default null selection has been appended manually in demo.js
This is because the options in select are overritten when options are appended.-->
</select>
</div>
<div class="col-md-4">
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
<p>Brightness</p>
</div>
<div>
<div class="radio" data-value="contrast">
<i class="fa fa-adjust fa-4x i-over"></i>
</div>
<div class="row center-align">
<button id="resetButton" class="btn btn-default btn-lg"
style=" margin: 20px 35px 0px 35px; width:100%;">Clear All Steps</button>
<p>Contrast</p>
</div>
<div>
<div class="radio" data-value="saturation">
<i class="fa fa-tint fa-4x i-over i-small"></i>
</div>
<p>Saturation</p>
</div>
<div>
<div class="radio" data-value="rotate">
<i class="fa fa-rotate-right fa-4x i-over"></i>
</div>
<p>Rotate</p>
</div>
<div>
<div class="radio" data-value="crop">
<i class="fa fa-crop fa-4x i-over"></i>
</div>
<p>Crop</p>
</div>
</div>
</section>
<div class="row center-align">
<div class="col-md-8">
<select id="selectStep" >
<!-- The default null selection has been appended manually in demo.js
This is because the options in select are overritten when options are appended.-->
</select>
</div>
<div class="col-md-4">
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button></div>
</div>
<div class="row center-align">
<button id="resetButton" class="btn btn-default btn-lg" style=" margin: 20px 35px 0px 35px; width:100%;">Clear All Steps</button>
</div>
</div>
</div>
</section>
<section id="sequence-actions" class="panel">
<div class="panel-body">
<div class="modal fade" id="js-download-gif-modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Your gif is ready</h4>
</div>
<div class="modal-body">
@@ -181,58 +170,59 @@
</div>
</div>
<div class="col-sm-4">
<section id="dwnld" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="text-align:center;">
<h2 style="margin-top:20px">Save</h2>
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
<option value="save-image">Save as PNG</option>
<option value="save-gif">Save as GIF (all steps)</option>
<option value="save-seq">Save sequence</option>
<option value="save-seq-string">Save sequence string</option>
</select>
<p><button id="saveButton" class="btn btn-primary btn-lg save-button">Save</button></p>
<p><button class="btn btn-default btn-lg js-view-as-gif" id="gif">Preview GIF</button></p>
</div>
</div>
</section>
</div>
<div class="col-sm-4">
<section id="dwnld" class="panel panel-primary">
<div class="form-inline">
<div class="panel-body">
<div style="text-align:center;">
<h2 style="margin-top:20px">Save</h2>
<select class="form-control input-md" id="selectSaveOption" style="margin-top:20px">
<option>Save as PNG</option>
<option>Save as GIF (all steps)</option>
<option>Save sequence</option>
<option>Save sequence string</option>
</select>
<p><button id="saveButton" class="btn btn-primary btn-lg" style="margin-top:20px; margin-bottom:0px;align:center; width:100%;">Save</button></p>
<p><button class="btn btn-default js-view-as-gif" id="gif" style="align:center;">Preview GIF</button></p>
</div>
</section>
</div>
</div>
</section>
</div>
</div>
<footer>
<hr style="margin:20px;"><center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
<div class="row">
<div class="col-md-6">
<h2>Need Help?</h2>
<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://publiclab.org/chat">Ask in our chatroom</a>
</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help improve on Github
</p>
<p>
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer">View the code &raquo;</a>
</p>
</div>
</div>
</footer>
<footer>
<hr style="margin:20px;">
<center><button class="btn btn-default btn-sm" id="clear-cache">Clear offline cache</button></center>
<div class="row">
<div class="col-md-6">
<h2>Need Help?</h2>
<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://publiclab.org/chat">Ask in our chatroom</a>
</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help improve on Github
</p>
<p>
<a class="btn btn-default" href="https://github.com/publiclab/image-sequencer">View the code &raquo;</a>
</p>
</div>
</div>
</footer>
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<button id="move-up"><i class="fa fa-arrow-circle-o-up"></i></button>
<script type="text/javascript">
$(function () {
var sequencer;
})
</script>
<script async src="../node_modules/opencv.js/opencv.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
var sequencer;
})
</script>
</body>

View File

@@ -4,11 +4,11 @@ var setupCache = function() {
.then(function(registration) {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
console.log(installingWorker);
console.log(installingWorker)
if (installingWorker.state === 'installed') {
location.reload();
}
};
}
console.log('Registration successful, scope is:', registration.scope);
})
.catch(function(error) {
@@ -19,12 +19,12 @@ var setupCache = function() {
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
$('#clear-cache').append(' ' + cacheName);
$("#clear-cache").append(" " + cacheName);
});
});
}
$('#clear-cache').click(function() {
$("#clear-cache").click(function() {
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
@@ -34,6 +34,6 @@ var setupCache = function() {
}
location.reload();
});
};
}
module.exports = setupCache;
module.exports = setupCache;

View File

@@ -2,52 +2,51 @@ var urlHash = require('./urlHash.js');
function DefaultHtmlSequencerUi(_sequencer, options) {
options = options || {};
var addStepSel = options.addStepSel = options.addStepSel || '#addStep';
var removeStepSel = options.removeStepSel = options.removeStepSel || 'button.remove';
var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep';
var addStepSel = options.addStepSel = options.addStepSel || "#addStep";
var removeStepSel = options.removeStepSel = options.removeStepSel || "button.remove";
var selectStepSel = options.selectStepSel = options.selectStepSel || "#selectStep";
function onLoad() {
importStepsFromUrlHash();
if ($('#selectStep').val() === 'none')
$(addStepSel + ' #add-step-btn').prop('disabled', true);
handleSaveSequence();
if ($('#selectStep').val()==='none')
$(addStepSel + " #add-step-btn").prop("disabled", true);
handleSaveSequence();
}
// look up needed steps from Url Hash:
function importStepsFromUrlHash() {
var hash = urlHash.getUrlHashParameter('steps');
var hash = urlHash.getUrlHashParameter("steps");
if (hash) {
_sequencer.importString(hash);
_sequencer.run({ index: 0 });
}
urlHash.setUrlHashParameter('steps', sequencer.toString());
urlHash.setUrlHashParameter("steps", sequencer.toString());
}
function selectNewStepUi() {
var m = $(addStepSel + ' select').val();
var m = $(addStepSel + " select").val();
if(!m) m = arguments[0];
$(addStepSel + ' .info').html(_sequencer.modulesInfo(m).description);
$(addStepSel + ' #add-step-btn').prop('disabled', false);
$(addStepSel + " .info").html(_sequencer.modulesInfo(m).description);
$(addStepSel + " #add-step-btn").prop("disabled", false);
}
function removeStepUi() {
var index = $(removeStepSel).index(this) + 1;
sequencer.removeSteps(index).run({ index: index - 1 });
// remove from URL hash too
urlHash.setUrlHashParameter('steps', sequencer.toString());
urlHash.setUrlHashParameter("steps", sequencer.toString());
//disable save-sequence button if all steps are removed
handleSaveSequence();
}
function addStepUi() {
if ($(addStepSel + ' select').val() == 'none') return;
var newStepName;
if(typeof arguments[0] !== 'string')
newStepName = $(addStepSel + ' select option').html().toLowerCase().split(' ').join('-');
else newStepName = arguments[0];
if ($(addStepSel + " select").val() == "none") return;
var newStepName = $(addStepSel + " select").val();
if(!newStepName) newStepName = arguments[0]
/*
* after adding the step we run the sequencer from defined step
* and since loadImage is not a part of the drawarray the step lies at current
@@ -56,28 +55,28 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
var sequenceLength = 1;
if (sequencer.sequences[newStepName]) {
sequenceLength = sequencer.sequences[newStepName].length;
} else if (sequencer.modules[newStepName][1]['length']) {
sequenceLength = sequencer.modules[newStepName][1]['length'];
} else if (sequencer.modules[newStepName][1]["length"]) {
sequenceLength = sequencer.modules[newStepName][1]["length"];
}
_sequencer
.addSteps(newStepName, options)
.run({ index: _sequencer.steps.length - sequenceLength - 1 });
$(addStepSel + ' .info').html('Select a new module to add to your sequence.');
$(addStepSel + ' select').val('none');
$(addStepSel + " .info").html("Select a new module to add to your sequence.");
$(addStepSel + " select").val("none");
//enable save-sequence button if disabled initially
handleSaveSequence();
// add to URL hash too
urlHash.setUrlHashParameter('steps', _sequencer.toString());
urlHash.setUrlHashParameter("steps", _sequencer.toString())
}
function handleSaveSequence(){
var stepCount = sequencer.steps.length;
if(stepCount < 2)
$(' #save-seq').prop('disabled', true);
var stepCount=sequencer.steps.length;
if(stepCount<2)
$(" #save-seq").prop("disabled", true);
else
$(' #save-seq').prop('disabled', false);
$(" #save-seq").prop("disabled", false);
}
return {
@@ -86,7 +85,7 @@ function DefaultHtmlSequencerUi(_sequencer, options) {
selectNewStepUi: selectNewStepUi,
removeStepUi: removeStepUi,
addStepUi: addStepUi
};
}
}
module.exports = DefaultHtmlSequencerUi;

View File

@@ -8,41 +8,38 @@
// output values, step information.
// See documetation for more details.
const intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js'),
urlHash = require('./urlHash.js'),
_ = require('lodash'),
mapHtmlTypes = require('./mapHtmltypes'),
scopeQuery = require('./scopeQuery');
var intermediateHtmlStepUi = require('./intermediateHtmlStepUi.js');
var urlHash = require('./urlHash.js');
var _ = require('lodash');
var mapHtmlTypes = require('./mapHtmltypes');
function DefaultHtmlStepUi(_sequencer, options) {
let $step, $stepAll;
options = options || {};
var stepsEl = options.stepsEl || document.querySelector('#steps');
var selectStepSel = options.selectStepSel = options.selectStepSel || '#selectStep';
var stepsEl = options.stepsEl || document.querySelector("#steps");
var selectStepSel = options.selectStepSel = options.selectStepSel || "#selectStep";
function onSetup(step, stepOptions) {
if (step.options && step.options.description)
step.description = step.options.description;
step.ui =
'\
<div class="container-fluid step-container">\
<form class="input-form">\
<div class="panel panel-default">\
<div class="panel-heading">\
<div class="trash-container pull-right"></div>\
<h3 class="panel-title">' +
'<span class="toggle">' + step.name + ' <span class="caret toggleIcon rotated"></span>\
<h3 class="panel-title">' +
'<span class="toggle">' +step.name + ' <span class="caret"></span>\
<span class="load-spin pull-right" style="display:none;padding:1px 8px;"><i class="fa fa-circle-o-notch fa-spin"></i></span>\
</h3>\
</div>\
<form class="input-form">\
<div class="panel-body cal collapse in">\
<div class="row step">\
<div class="col-md-4 details container-fluid">\
<div class="cal collapse in"><p>' +
'<i>' + (step.description || '') + '</i>' +
'<i>' + (step.description || "") + '</i>' +
'</p></div>\
</div>\
<div class="col-md-8 cal collapse in step-column">\
@@ -54,8 +51,8 @@ function DefaultHtmlStepUi(_sequencer, options) {
</div>\
</div>\
<div class="panel-footer cal collapse in"></div>\
</form>\
</div>\
</form>\
</div>';
var tools =
@@ -68,16 +65,10 @@ function DefaultHtmlStepUi(_sequencer, options) {
var util = intermediateHtmlStepUi(_sequencer, step);
var parser = new DOMParser();
step.ui = parser.parseFromString(step.ui, 'text/html');
step.ui = step.ui.querySelector('div.container-fluid');
$step = scopeQuery.scopeSelector(step.ui);
$stepAll = scopeQuery.scopeSelectorAll(step.ui);
step.ui.$step = $step;
step.ui.$stepAll = $stepAll;
step.linkElements = step.ui.querySelectorAll('a');
step.imgElement = $step('a img.img-thumbnail')[0];
step.ui = parser.parseFromString(step.ui, "text/html");
step.ui = step.ui.querySelector("div.container-fluid");
step.linkElements = step.ui.querySelectorAll("a");
step.imgElement = step.ui.querySelector("a img.img-thumbnail");
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
var inputs = _sequencer.modulesInfo(step.name).inputs;
@@ -86,135 +77,113 @@ function DefaultHtmlStepUi(_sequencer, options) {
for (var paramName in merged) {
var isInput = inputs.hasOwnProperty(paramName);
var html = '';
var html = "";
var inputDesc = isInput ? mapHtmlTypes(inputs[paramName]) : {};
if (!isInput) {
html += '<span class="output"></span>';
}
else if (inputDesc.type.toLowerCase() == 'select') {
} else if (inputDesc.type.toLowerCase() == "select") {
html += '<select class="form-control target" name="' + paramName + '">';
for (var option in inputDesc.values) {
html += '<option>' + inputDesc.values[option] + '</option>';
html += "<option>" + inputDesc.values[option] + "</option>";
}
html += '</select>';
}
else {
html += "</select>";
} else {
let paramVal = step.options[paramName] || inputDesc.default;
html =
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal +
'" placeholder ="' +
(inputDesc.placeholder || "");
if (inputDesc.id == 'color-picker') { // separate input field for color-picker
if (inputDesc.type.toLowerCase() == "range") {
html +=
'<div id="color-picker" class="input-group colorpicker-component">' +
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal + '">' + '<span class="input-group-addon"><i></i></span>' +
'</div>';
}
else { // use this if the the field isn't color-picker
html =
'<input class="form-control target" type="' +
inputDesc.type +
'" name="' +
paramName +
'" value="' +
paramVal +
'" placeholder ="' +
(inputDesc.placeholder || '');
if (inputDesc.type.toLowerCase() == 'range') {
html +=
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
(inputDesc.step ? inputDesc.step : 1) + '">' + '<span>' + paramVal + '</span>';
'"min="' +
inputDesc.min +
'"max="' +
inputDesc.max +
'"step="' +
(inputDesc.step ? inputDesc.step : 1)+ '">' + '<span>' + paramVal + '</span>';
}
else html += '">';
}
else html += '">';
}
var div = document.createElement('div');
div.className = 'row';
div.setAttribute('name', paramName);
var div = document.createElement("div");
div.className = "row";
div.setAttribute("name", paramName);
var description = inputs[paramName].desc || paramName;
div.innerHTML =
'<div class=\'det cal collapse in\'>\
<label for=\'' +
"<div class='det cal collapse in'>\
<label for='" +
paramName +
'\'>' +
"'>" +
description +
'</label>\
' +
"</label>\
" +
html +
'\
</div>';
$step('div.details').append(div);
"\
</div>";
step.ui.querySelector("div.details").appendChild(div);
}
$step('div.panel-footer').append(
$(step.ui.querySelector("div.panel-footer")).append(
'<div class="cal collapse in"><button type="submit" class="btn btn-sm btn-default btn-save" disabled = "true" >Apply</button> <small style="padding-top:2px;">Press apply to see changes</small></div>'
);
$step('div.panel-footer').prepend(
$(step.ui.querySelector("div.panel-footer")).prepend(
'<button class="pull-right btn btn-default btn-sm insert-step" >\
<span class="insert-text"><i class="fa fa-plus"></i> Insert Step</span><span class="no-insert-text" style="display:none">Close</span></button>\
<button class="pull-right btn btn-default btn-sm download-btn" style="margin-right:2px" >\
<i class="fa fa-download"></i>\
</button>'
);
<i class="fa fa-plus"></i> Insert Step\
</button>'
);
}
if (step.name != 'load-image') {
$step('div.trash-container')
if (step.name != "load-image") {
step.ui
.querySelector("div.trash-container")
.prepend(
parser.parseFromString(tools, 'text/html').querySelector('div')
parser.parseFromString(tools, "text/html").querySelector("div")
);
$stepAll('.remove').on('click', function() {notify('Step Removed', 'remove-notification');});
$stepAll('.insert-step').on('click', function() { util.insertStep(step.ID); });
$(step.ui.querySelectorAll(".remove")).on('click', function() {notify('Step Removed','remove-notification')});
$(step.ui.querySelectorAll(".insert-step")).on('click', function() { util.insertStep(step.ID) });
// Insert the step's UI in the right place
if (stepOptions.index == _sequencer.steps.length) {
stepsEl.appendChild(step.ui);
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
if($('#steps .step-container:nth-last-child(2)'))
$('#steps .step-container:nth-last-child(2) .insert-step').prop('disabled', false);
}
else {
$("#steps .step-container:nth-last-child(1) .insert-step").prop('disabled',true);
if($("#steps .step-container:nth-last-child(2)"))
$("#steps .step-container:nth-last-child(2) .insert-step").prop('disabled',false);
} else {
stepsEl.insertBefore(step.ui, $(stepsEl).children()[stepOptions.index]);
}
}
else {
$('#load-image').append(step.ui);
$("#load-image").append(step.ui);
}
$step('.toggle').on('click', () => {
$step('.toggleIcon').toggleClass('rotated');
$stepAll('.cal').collapse('toggle');
$(step.ui.querySelector(".toggle")).on("click", () => {
$(step.ui.querySelector('.toggleIcon')).toggleClass('fa-caret-up').toggleClass('fa-caret-down');
$(step.ui.querySelectorAll(".cal")).collapse('toggle');
});
$(step.imgElement).on('mousemove', _.debounce(() => imageHover(step), 150));
$(step.imgElement).on('click', (e) => {e.preventDefault(); });
$stepAll('#color-picker').colorpicker();
$(step.imgElement).on("mousemove", _.debounce(() => imageHover(step), 150));
function saveOptions(e) { // 1. SAVE OPTIONS
function saveOptions(e) {
e.preventDefault();
if (optionsChanged){
$step('div.details')
.find('input,select')
$(step.ui.querySelector("div.details"))
.find("input,select")
.each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false);
step.options[$(input).attr('name')] = $(input).val();
step.options[$(input).attr("name")] = $(input).val();
});
_sequencer.run({ index: step.index - 1 });
// modify the url hash
urlHash.setUrlHashParameter('steps', _sequencer.toString());
urlHash.setUrlHashParameter("steps", _sequencer.toString())
// disable the save button
$step('.btn-save').prop('disabled', true);
$(step.ui.querySelector('.btn-save')).prop('disabled', true);
optionsChanged = false;
changedInputs = 0;
}
@@ -225,19 +194,19 @@ function DefaultHtmlStepUi(_sequencer, options) {
changedInputs += hasChangedBefore ? inputChanged ? 0 : -1 : inputChanged ? 1 : 0;
optionsChanged = changedInputs > 0;
$step('.btn-save').prop('disabled', !optionsChanged);
$(step.ui.querySelector('.btn-save')).prop('disabled', !optionsChanged);
return inputChanged;
}
var
var
changedInputs = 0,
optionsChanged = false;
$step('.input-form').on('submit', saveOptions);
$stepAll('.target').each(function(i, input) {
$(step.ui.querySelector('.input-form')).on('submit', saveOptions);
$(step.ui.querySelectorAll('.target')).each(function(i, input) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false)
.on('input change', function() {
.on('input', function() {
$(this)
.focus()
.data('hasChangedBefore',
@@ -245,32 +214,32 @@ function DefaultHtmlStepUi(_sequencer, options) {
$(this).val(),
$(this).data('initValue'),
$(this).data('hasChangedBefore')
)
);
});
});
)
)
})
})
$('input[type="range"]').on('input', function() {
$(this).next().html($(this).val());
});
$(this).next().html($(this).val());
})
}
function onDraw() {
$step('.load').show();
$step('img').hide();
$stepAll('.load-spin').show();
function onDraw(step) {
$(step.ui.querySelector(".load")).show();
$(step.ui.querySelector("img")).hide();
$(step.ui.querySelectorAll(".load-spin")).show();
}
function onComplete(step) {
$step('img').show();
$stepAll('.load-spin').hide();
$step('.load').hide();
$(step.ui.querySelector("img")).show();
$(step.ui.querySelectorAll(".load-spin")).hide();
$(step.ui.querySelector(".load")).hide();
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
var imgthumbnail = $step('.img-thumbnail').getDomElem();
step.imgElement.src = (step.name == "load-image") ? step.output.src : step.output;
var imgthumbnail = step.ui.querySelector(".img-thumbnail");
for (let index = 0; index < step.linkElements.length; index++) {
if (step.linkElements[index].contains(imgthumbnail))
step.linkElements[index].href = step.imgElement.src;
@@ -278,24 +247,14 @@ function DefaultHtmlStepUi(_sequencer, options) {
// TODO: use a generalized version of this
function fileExtension(output) {
return output.split('/')[1].split(';')[0];
return output.split("/")[1].split(";")[0];
}
$stepAll('.download-btn').on('click', () => {
for (let index = 0; index < step.linkElements.length; index++) {
for (let index = 0; index < step.linkElements.length; index++){
var element = document.createElement('a');
element.setAttribute('href', step.linkElements[index].href);
element.setAttribute('download', step.name + '.' + fileExtension(step.imgElement.src));
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
});
step.linkElements[index].download = step.name + "." + fileExtension(step.imgElement.src);
step.linkElements[index].target = "_blank";
}
// fill inputs with stored step options
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
@@ -303,19 +262,19 @@ function DefaultHtmlStepUi(_sequencer, options) {
var outputs = _sequencer.modulesInfo(step.name).outputs;
for (var i in inputs) {
if (step.options[i] !== undefined) {
if (inputs[i].type.toLowerCase() === 'input')
$step('div[name="' + i + '"] input')
if (inputs[i].type.toLowerCase() === "input")
$(step.ui.querySelector('div[name="' + i + '"] input'))
.val(step.options[i])
.data('initValue', step.options[i]);
if (inputs[i].type.toLowerCase() === 'select')
$step('div[name="' + i + '"] select')
if (inputs[i].type.toLowerCase() === "select")
$(step.ui.querySelector('div[name="' + i + '"] select'))
.val(step.options[i])
.data('initValue', step.options[i]);
}
}
for (var i in outputs) {
if (step[i] !== undefined)
$step('div[name="' + i + '"] input')
$(step.ui.querySelector('div[name="' + i + '"] input'))
.val(step[i]);
}
}
@@ -325,24 +284,24 @@ function DefaultHtmlStepUi(_sequencer, options) {
var img = $(step.imgElement);
img.mousemove(function(e) {
img.mousemove(function(e) {
var canvas = document.createElement('canvas');
canvas.width = img.width();
canvas.height = img.height();
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
context.drawImage(this,0,0);
var offset = $(this).offset();
var xPos = e.pageX - offset.left;
var yPos = e.pageY - offset.top;
var myData = context.getImageData(xPos, yPos, 1, 1);
img[0].title = 'rgb: ' + myData.data[0] + ',' + myData.data[1] + ',' + myData.data[2];//+ rgbdata;
});
img[0].title = "rgb: " +myData.data[0]+","+ myData.data[1]+","+myData.data[2];//+ rgbdata;
});
}
function onRemove(step) {
step.ui.remove();
$('#steps .step-container:nth-last-child(1) .insert-step').prop('disabled', true);
$("#steps .step-container:nth-last-child(1) .insert-step").prop('disabled',true);
$('div[class*=imgareaselect-]').remove();
}
@@ -350,17 +309,17 @@ function DefaultHtmlStepUi(_sequencer, options) {
return step.imgElement;
}
function notify(msg, id){
if ($('#' + id).length == 0) {
function notify(msg,id){
if ($('#'+id).length == 0) {
var notification = document.createElement('span');
notification.innerHTML = ' <i class="fa fa-info-circle" aria-hidden="true"></i> ' + msg ;
notification.id = id;
notification.classList.add('notification');
notification.classList.add("notification");
$('body').append(notification);
}
$('#' + id).fadeIn(500).delay(200).fadeOut(500);
$('#'+id).fadeIn(500).delay(200).fadeOut(500);
}
@@ -369,16 +328,17 @@ function DefaultHtmlStepUi(_sequencer, options) {
onSetup: onSetup,
onComplete: onComplete,
onRemove: onRemove,
onDraw: onDraw,
onDraw: onDraw,
notify: notify,
imageHover: imageHover
};
}
}
if(typeof window === 'undefined'){
module.exports = {
if(typeof window === "undefined"){
module.exports={
DefaultHtmlStepUi: DefaultHtmlStepUi
};
}
}
module.exports = DefaultHtmlStepUi;

View File

@@ -1,77 +1,55 @@
function generatePreview(previewStepName, customValues, path, selector) {
var previewSequencer = ImageSequencer();
function insertPreview(src) {
var img = document.createElement('img');
img.classList.add('img-thumbnail');
img.classList.add('no-border');
img.src = src;
$(img).css('max-width', '200%');
$(img).css('transform', 'translateX(-20%)');
$(selector + ' .radio-group').find('div').each(function() {
if ($(this).find('div').attr('data-value') === previewStepName) {
$(this).find('div').append(img);
}
});
}
function loadPreview() {
if (previewStepName === 'crop') {
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
if(previewStepName === 'resize')
insertPreview(path);
else
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, selector) {
$(selector + ' img').remove();
var previewSequencerSteps = {
'resize': '125%',
'brightness': '175',
'saturation': '0.5',
'rotate': 90,
'contrast': 90,
'crop': {
'x': 0,
'y': 0,
'w': '(50%)',
'h': '(50%)',
'noUI': true
}
};
var img = new Image();
img.onload = function(){
var height = img.height;
var width = img.width;
let percentage = (80 / height) * 100; //take the min resize value that fits the preview area => (new-width/orig_ht) - '80 as the preview area has 80*80 dimension
percentage = Math.max((80 / width) * 100, percentage); // make sure that one dimension doesn't resize greater, leading distorting preview-area fitting
percentage = Math.ceil(percentage);
var sequencer = ImageSequencer();
sequencer.loadImage(src, function(){
this.addSteps('resize', {['resize']: percentage + '%'});
this.run((src)=>{
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
var previewSequencer = ImageSequencer();
function insertPreview(src) {
var img = document.createElement('img');
img.classList.add('img-thumbnail')
img.classList.add('no-border');
img.src = src;
$(img).css("max-width", "200%");
$(img).css("transform", "translateX(-20%)");
var stepDiv = $('#'+selector+' .row').find('div').each(function() {
if ($(this).find('div').attr('data-value') === previewStepName) {
$(this).find('div').append(img);
}
});
});
};
img.src = src;
}
}
function loadPreview() {
if (previewStepName === "crop") {
previewSequencer.addSteps(previewStepName, customValues).run(insertPreview);
}
else {
previewSequencer.addSteps(previewStepName, { [previewStepName]: customValues }).run(insertPreview);
}
}
previewSequencer.loadImage(path, loadPreview);
}
function updatePreviews(src, selector) {
$('#'+selector+' img').remove();
var previewSequencerSteps = {
"resize": "125%",
"brightness": "175",
"saturation": "0.5",
"rotate": 90,
"contrast": 90,
"crop": {
"x": 0,
"y": 0,
"w": "(50%)",
"h": "(50%)",
"noUI": true
}
}
Object.keys(previewSequencerSteps).forEach(function (step, index) {
generatePreview(step, Object.values(previewSequencerSteps)[index], src, selector);
});
}
module.exports = {
generatePreview : generatePreview,
updatePreviews : updatePreviews
};
}

View File

@@ -1,164 +1,139 @@
var urlHash = require('./urlHash.js'),
insertPreview = require('./insertPreview.js');
insertPreview = require('./insertPreview.js');
function IntermediateHtmlStepUi(_sequencer, step, options) {
function stepUI() {
return '<div class="row insertDiv collapse">\
<section class="panel panel-primary .insert-step">\
<button class="btn btn-default close-insert-box"><i class="fa fa-times" aria-hidden="true"></i> Close</button>\
<div class="form-inline">\
<div class="panel-body">\
<p class="info">Select a new module to add to your sequence.</p>\
<div class="row center-align radio-group">\
<div>\
<div class="radio" data-value="resize">\
<i class="fa fa-arrows-alt fa-4x i-over"></i>\
</div>\
<p>Resize</p>\
</div>\
<div>\
<div class="radio" data-value="brightness">\
<i class="fa fa-sun-o fa-4x i-over"></i>\
</div>\
<p>Brightness</p>\
</div>\
<div>\
<div class="radio" data-value="contrast">\
<i class="fa fa-adjust fa-4x i-over"></i>\
</div>\
<p>Contrast</p>\
</div>\
<div>\
<div class="radio" data-value="saturation">\
<i class="fa fa-tint fa-4x i-over i-small"></i>\
</div>\
<p>Saturation</p>\
</div>\
<div>\
<div class="radio" data-value="rotate">\
<i class="fa fa-rotate-right fa-4x i-over"></i>\
</div>\
<p>Rotate</p>\
</div>\
<div>\
<div class="radio" data-value="crop">\
<i class="fa fa-crop fa-4x i-over"></i>\
</div>\
<p>Crop</p>\
</div>\
return '<div class="row insertDiv">\
<div class="col-md-6 col-md-offset-2" style="margin-top:5%">\
<section id="insertStep" class="panel panel-primary">\
<div class="form-inline">\
<div class="panel-body">\
<p class="info">Select a new module to add to your sequence.</p>\
<div class="row center-align radio-group">\
<div>\
<div class="radio" data-value="resize">\
<i class="fa fa-arrows-alt fa-4x i-over"></i>\
</div>\
<p>Resize</p>\
</div>\
<div class="row center-align">\
<div class="col-md-8">\
<select class="insert-step-select">\
<!-- The default null selection has been appended manually in demo.js\
This is because the options in select are overritten when options are appended.-->\
</select>\
<div>\
<div class="col-md-4">\
<button class="btn btn-success btn-lg insert-save-btn add-step-btn" name="add">Add Step</button>\
<div>\
<div>\
<div class="radio" data-value="brightness">\
<i class="fa fa-sun-o fa-4x i-over"></i>\
</div>\
<p>Brightness</p>\
</div>\
<div>\
<div class="radio" data-value="contrast">\
<i class="fa fa-adjust fa-4x i-over"></i>\
</div>\
<p>Contrast</p>\
</div>\
<div>\
<div class="radio" data-value="saturation">\
<i class="fa fa-tint fa-4x i-over i-small"></i>\
</div>\
<p>Saturation</p>\
</div>\
<div>\
<div class="radio" data-value="rotate">\
<i class="fa fa-rotate-right fa-4x i-over"></i>\
</div>\
<p>Rotate</p>\
</div>\
<div>\
<div class="radio" data-value="crop">\
<i class="fa fa-crop fa-4x i-over"></i>\
</div>\
<p>Crop</p>\
</div>\
</div>\
<div class="row center-align">\
<div class="col-md-8">\
<select class="form-control input-lg" id="selectStep">\
<!-- The default null selection has been appended manually in demo.js\
This is because the options in select are overritten when options are appended.-->\
</select>\
<div>\
<div class="col-md-4">\
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button>\
<div>\
</div>\
</div>\
</section>\
</div>\
</section>\
</div>';
}
function selectNewStepUi($step) {
var insertSelect = $step('.insert-step-select');
var m = insertSelect.val();
$step('.insertDiv .info').html(_sequencer.modulesInfo(m).description);
$step('.insertDiv .add-step-btn').prop('disabled', false);
function selectNewStepUi() {
var m = $("#insertStep select").val();
$("#insertStep .info").html(_sequencer.modulesInfo(m).description);
$("#insertStep #add-step-btn").prop("disabled", false);
}
var toggleDiv = function($step, callback = function(){}){
$step('.insertDiv').collapse('toggle');
if ($step('.insert-text').css('display') != 'none'){
$step('.insert-text').fadeToggle(200, function(){$step('.no-insert-text').fadeToggle(200, callback);});
}
else {
$step('.no-insert-text').fadeToggle(200, function(){$step('.insert-text').fadeToggle(200, callback);});
}
};
insertStep = function (id) {
const $step = step.ui.$step,
$stepAll = step.ui.$stepAll;
var modulesInfo = _sequencer.modulesInfo();
var parser = new DOMParser();
var addStepUI = stepUI();
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
if ($step('.insertDiv').length > 0){
toggleDiv($step);
}
else {
step.ui
.querySelector('div.step')
.insertAdjacentElement('afterend',
addStepUI
);
toggleDiv($step, function(){
insertPreview.updatePreviews(step.output, '.insertDiv');
});
}
$step('.insertDiv .close-insert-box').off('click').on('click', function(){toggleDiv(function(){});});
var insertStepSelect = $step('.insert-step-select');
insertStepSelect.html('');
addStepUI = parser.parseFromString(addStepUI, "text/html").querySelector("div")
step.ui
.querySelector("div.step")
.insertAdjacentElement('afterend',
addStepUI
);
insertPreview.updatePreviews(step.output,'insertStep');
var insertStepSelect = $("#insertStep select");
insertStepSelect.html("");
// Add modules to the insertStep dropdown
for (var m in modulesInfo) {
if (modulesInfo[m] !== undefined)
insertStepSelect.append(
'<option value="' + m + '">' + modulesInfo[m].name + '</option>'
'<option value="' + m + '">' + modulesInfo[m].name + "</option>"
);
}
insertStepSelect.selectize({
$('#insertStep #add-step-btn').selectize({
sortField: 'text'
});
$step('.inserDiv .add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="" disabled selected>Select a Module</option>');
$step('.insertDiv .radio-group .radio').on('click', function () {
$('#insertStep #add-step-btn').prop('disabled', true);
insertStepSelect.append('<option value="none" disabled selected>More modules...</option>');
$('#insertStep .radio-group .radio').on("click", function () {
$(this).parent().find('.radio').removeClass('selected');
$(this).addClass('selected');
newStep = $(this).attr('data-value');
$step('.insert-step-select').val(newStep);
selectNewStepUi($step);
insert(id, $step);
insertStepSelect.val(newStep);
selectNewStepUi();
insert(id);
$(this).removeClass('selected');
});
insertStepSelect.on('change', () => {selectNewStepUi($step);});
$step('.insertDiv .add-step-btn').on('click', function () { insert(id, $step); });
};
$(step.ui.querySelector("#insertStep select")).on('change', selectNewStepUi);
$(step.ui.querySelector("#insertStep #add-step-btn")).on('click', function () { insert(id) });
}
function insert(id, $step) {
function insert(id) {
options = options || {};
var insertStepSelect = $step('.insert-step-select');
if (insertStepSelect.val() == 'none') return;
var insertStepSelect = $("#insertStep select");
if (insertStepSelect.val() == "none") return;
var newStepName = insertStepSelect.val();
toggleDiv($step);
var newStepName = insertStepSelect.val()
$('div .insertDiv').remove();
var sequenceLength = 1;
if (sequencer.sequences[newStepName]) {
sequenceLength = sequencer.sequences[newStepName].length;
} else if (sequencer.modules[newStepName][1]['length']) {
sequenceLength = sequencer.modules[newStepName][1]['length'];
} else if (sequencer.modules[newStepName][1]["length"]) {
sequenceLength = sequencer.modules[newStepName][1]["length"];
}
_sequencer
.insertSteps(id + 1, newStepName).run({ index: id });
// add to URL hash too
urlHash.setUrlHashParameter('steps', _sequencer.toString());
urlHash.setUrlHashParameter("steps", _sequencer.toString());
}
return {
insertStep
};
}
}
module.exports = IntermediateHtmlStepUi;

View File

@@ -1,24 +1,24 @@
function mapHtmlTypes(inputInfo){
var htmlType;
switch(inputInfo.type.toLowerCase()){
case 'integer':
htmlType = inputInfo.min != undefined ? 'range' : 'number';
break;
case 'string':
htmlType = 'text';
break;
case 'select':
htmlType = 'select';
break;
case 'percentage':
htmlType = 'number';
break;
case 'float':
htmlType = inputInfo.min != undefined ? 'range' : 'text';
break;
default:
htmlType = 'text';
break;
case 'integer':
htmlType = inputInfo.min != undefined ? 'range' : 'number';
break;
case 'string':
htmlType = 'text';
break;
case 'select':
htmlType = 'select';
break;
case 'percentage':
htmlType = 'number';
break;
case 'float':
htmlType = inputInfo.min != undefined ? 'range' : 'text';
break;
default:
htmlType = 'text';
break;
}
var response = inputInfo;
response.type = htmlType;

View File

@@ -1,68 +0,0 @@
/**
* @method $scope
* @param {"DOMNode"} scope A DOM Node as the scope
*/
function $scope(scope) {
return function(queryString){
var element = $(scope.querySelector(queryString));
element.elem = function(queryString){
return new $scope(scope)(queryString);
};
element.elemAll = function(queryString){
return new $scopeAll(scope)(queryString);
};
element.getDomElem = function(i = 0){
return element[i];
};
element.getScope = () => scope;
return element;
};
}
/**
* @method $scopeAll
* @param {"DOMNode"} scope A DOM Node as the scope
*/
function $scopeAll(scope){
return function(queryString){
var element = $(scope.querySelectorAll(queryString));
element.elem = function(queryString){
return new $scope(scope)(queryString);
};
element.elemAll = function(queryString){
return new $scopeAll(scope)(queryString);
};
element.getDomElem = function(i = 0){
return element[i];
};
element.getScope = () => scope;
return element;
};
}
/**
* @method scopeSelector
* @description A scoped jQuery selector
* @param {"DOMNode"} scope DOM Node as the scope
*/
function scopeSelector(scope){
return $scope(scope);
}
/**
* @method scopeSelectorAll
* @description A scoped jQuery multiple selector
* @param {"DOMNode} scope DOM Node as the scope
*/
function scopeSelectorAll(scope){
return $scopeAll(scope);
}
module.exports = {
scopeSelector,
scopeSelectorAll
};

View File

@@ -17,7 +17,7 @@ self.addEventListener('activate', function(e) {
})
);
})
);
);
});
self.addEventListener('fetch', function(event) {
@@ -25,11 +25,11 @@ self.addEventListener('fetch', function(event) {
caches.open(staticCacheName).then(function(cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function(response) {
if(event.request.method == 'GET')
if(event.request.method == "GET")
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
});

View File

@@ -42,8 +42,8 @@ function setUrlHashParameter(param, value) {
}
module.exports = {
getUrlHashParameter: getUrlHashParameter,
setUrlHashParameter: setUrlHashParameter,
getUrlHashParameters: getUrlHashParameters,
setUrlHashParameters: setUrlHashParameters
};
getUrlHashParameter: getUrlHashParameter,
setUrlHashParameter: setUrlHashParameter,
getUrlHashParameters: getUrlHashParameters,
setUrlHashParameters: setUrlHashParameters
}

View File

@@ -1,14 +1,14 @@
#!/usr/bin/env node
require('./src/ImageSequencer');
sequencer = ImageSequencer({ ui: true });
var fs = require('fs');
sequencer = ImageSequencer({ ui: false });
var fs = require('fs')
var program = require('commander');
var utils = require('./src/CliUtils');
var utils = require('./src/CliUtils')
var saveSequence = require('./src/cli/saveSequence.js');
var installModule = require('./src/cli/installModule.js');
var sequencerSteps = require('./src/cli/sequencerSteps.js');
var saveSequence = require('./src/cli/saveSequence.js')
var installModule = require('./src/cli/installModule.js')
var sequencerSteps = require('./src/cli/sequencerSteps.js')
function exit(message) {
console.error(message);
@@ -16,39 +16,39 @@ function exit(message) {
}
program
.version('0.1.0')
.option('-i, --image [PATH/URL]', 'Input image URL')
.option('-s, --step [step-name]', 'Name of the step to be added.')
.option('-o, --output [PATH]', 'Directory where output will be stored.')
.option('-b, --basic', 'Basic mode outputs only final image')
.option('-c, --config [Object]', 'Options for the step')
.option('--save-sequence [string]', 'Name space separated with Stringified sequence')
.option('--install-module [string]', 'Module name space seaprated npm package name')
.version("0.1.0")
.option("-i, --image [PATH/URL]", "Input image URL")
.option("-s, --step [step-name]", "Name of the step to be added.")
.option("-o, --output [PATH]", "Directory where output will be stored.")
.option("-b, --basic", "Basic mode outputs only final image")
.option("-c, --config [Object]", "Options for the step")
.option("--save-sequence [string]", "Name space separated with Stringified sequence")
.option('--install-module [string]', "Module name space seaprated npm package name")
.parse(process.argv);
if (program.saveSequence) saveSequence(program, sequencer);
if (program.saveSequence) saveSequence(program, sequencer)
else if (program.installModule) installModule(program, sequencer);
else if (program.installModule) installModule(program, sequencer)
else {
// Parse step into an array to allow for multiple steps.
if (!program.step) exit('No steps passed');
program.step = program.step.split(' ');
if (!program.step) exit("No steps passed");
program.step = program.step.split(" ");
// User must input an image.
if (!program.image) exit('Can\'t read file.');
if (!program.image) exit("Can't read file.");
// User must input an image.
fs.access(program.image, function(err) {
if (err) exit('Can\'t read file.');
if (err) exit("Can't read file.");
});
// User must input a step. If steps exist, check that every step is a valid step.
if (!program.step || !(utils.validateSteps(program.step, sequencer)))
exit('Please ensure all steps are valid.');
exit("Please ensure all steps are valid.");
// If there's no user defined output directory, select a default directory.
program.output = program.output || './output/';
program.output = program.output || "./output/";
// Set sequencer to log module outputs, if any.
sequencer.setUI({
@@ -57,19 +57,19 @@ else {
step.info = sequencer.modulesInfo(step.name);
for (var output in step.info.outputs) {
console.log('[' + program.step + ']: ' + output + ' = ' + step[output]);
console.log("[" + program.step + "]: " + output + " = " + step[output]);
}
},
notify: function(msg) {
console.log('\x1b[36m%s\x1b[0m', '🌟 ' + msg);
console.log('\x1b[36m%s\x1b[0m','🌟 '+msg);
}
});
// Finally, if everything is alright, load the image, add the steps and run the sequencer.
sequencer.loadImages(program.image, function() {
console.warn(
'\x1b[33m%s\x1b[0m',
'Please wait \n output directory generated will be empty until the execution is complete'
"\x1b[33m%s\x1b[0m",
"Please wait \n output directory generated will be empty until the execution is complete"
);
//Generate the Output Directory
@@ -82,7 +82,7 @@ else {
outputFilename = null;
}
sequencerSteps(program, sequencer, outputFilename);
sequencerSteps(program, sequencer, outputFilename)
});

6106
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,15 @@
{
"name": "image-sequencer",
"version": "3.5.1",
"version": "3.0.1",
"description": "A modular JavaScript image manipulation library modeled on a storyboard.",
"main": "src/ImageSequencer.js",
"scripts": {
"debug": "TEST=true node ./index.js -i ./examples/images/monarch.png -s invert",
"test": "TEST=true istanbul cover tape test/core/*.js test/core/ui/user-interface.js test/core/modules/*.js | tap-spec; node test/core/sequencer/benchmark.js; browserify test/core/sequencer/meta-modules.js test/core/sequencer/image-sequencer.js test/core/sequencer/chain.js test/core/sequencer/replace.js test/core/sequencer/import-export.js test/core/sequencer/run.js test/core/sequencer/dynamic-imports.js test/core/util/*.js | tape-run --render=\"tap-spec\"",
"test-ui": "node node_modules/jasmine/bin/jasmine test/ui/spec/*.js",
"test": "TEST=true tape test/core/*.js test/core/ui/user-interface.js test/core/modules/QR.js | tap-spec; browserify test/core/modules/image-sequencer.js test/core/modules/chain.js test/core/modules/meta-modules.js test/core/modules/replace.js test/core/modules/import-export.js test/core/modules/run.js test/core/modules/dynamic-imports.js test/core/util/parse-input.js test/core/modules/benchmark.js| tape-run --render=\"tap-spec\"",
"test-ui": "jasmine test/spec/*.js",
"setup": "npm i && npm i -g grunt grunt-cli && grunt build",
"start": "grunt serve"
},
"lint-staged": {
"*.js": [
"./node_modules/.bin/eslint --fix",
"git add"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/publiclab/image-sequencer.git"
@@ -30,81 +24,52 @@
"url": "https://github.com/publiclab/image-sequencer/issues"
},
"dependencies": {
"atob": "^2.1.2",
"base64-img": "^1.0.4",
"bootstrap": "~3.4.0",
"bootstrap-colorpicker": "^2.5.3",
"buffer": "~5.4.0",
"buffer": "~5.2.1",
"commander": "^2.11.0",
"compressorjs": "^1.0.5",
"data-uri-to-buffer": "^2.0.0",
"downloadjs": "^1.4.7",
"eslint": "^6.1.0",
"fisheyegl": "^0.1.2",
"font-awesome": "~4.7.0",
"geotiff": "^1.0.0-beta.6",
"get-pixels": "~3.3.0",
"gifshot": "^0.4.5",
"glfx": "0.0.4",
"gpu.js": "^2.0.0-rc.12",
"image-sequencer-invert": "^1.0.0",
"imagejs": "0.0.9",
"imagemin": "^7.0.0",
"imagemin-jpegtran": "^6.0.0",
"imagemin-pngquant": "^8.0.0",
"imgareaselect": "git://github.com/jywarren/imgareaselect.git#v1.0.0-rc.2",
"istanbul": "^0.4.5",
"jasmine": "^3.4.0",
"jquery": "^3.3.1",
"jsdom": "^15.0.0",
"jsdom": "^14.0.0",
"jsqr": "^1.1.1",
"lodash": "^4.17.11",
"matcher-core": "git@github.com:publiclab/matcher-core.git#matcher-node",
"ndarray": "^1.0.18",
"opencv.js": "^1.2.1",
"ndarray-gaussian-filter": "^1.0.0",
"ora": "^3.0.0",
"pace": "0.0.4",
"puppeteer": "^1.14.0",
"qrcode": "^1.3.3",
"readline-sync": "^1.4.7",
"save-pixels": "~2.3.4",
"selectize": "^0.12.6",
"spawn-sync": "^2.0.0",
"urify": "^2.1.1",
"webgl-distort": "0.0.2"
"urify": "^2.1.1"
},
"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/plugin-proposal-object-rest-spread": "^7.4.3",
"@babel/plugin-syntax-object-rest-spread": "^7.2.0",
"babelify": "^10.0.0",
"base64-img": "^1.0.4",
"browserify": "16.2.3",
"eslint": "^6.1.0",
"grunt": "^1.0.3",
"grunt-browser-sync": "^2.2.0",
"grunt-browserify": "^5.0.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-uglify-es": "^3.3.0",
"grunt-contrib-watch": "^1.1.0",
"husky": "^2.2.0",
"image-filter-core": "~2.0.2",
"image-filter-threshold": "~2.0.1",
"jasmine-core": "^3.3.0",
"jasmine-jquery": "^2.1.1",
"jasmine-spec-reporter": "^4.2.1",
"lint-staged": "^9.1.0",
"looks-same": "^7.0.0",
"matchdep": "^2.0.0",
"tap-spec": "^5.0.0",
"tape": "^4.9.2",
"tape-run": "^6.0.0",
"tape-run": "^5.0.0",
"uglify-es": "^3.3.7"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"homepage": "https://sequencer.publiclab.org",
"bin": {
"sequencer": "./index.js"

View File

@@ -0,0 +1,42 @@
describe('Default sequencer HTML', function() {
var DefaultHtmlSequencerUi = require('../examples/lib/defaultHtmlSequencerUi')
var sequencer = require('../src/ImageSequencer')()
var defaultHtmlSequencerUi;
beforeEach(()=>{
defaultHtmlSequencerUi = new DefaultHtmlSequencerUi(sequencer)
spyOn(defaultHtmlSequencerUi,'onLoad')
spyOn(defaultHtmlSequencerUi,'selectNewStepUi')
spyOn(defaultHtmlSequencerUi,'removeStepUi')
spyOn(defaultHtmlSequencerUi,'addStepUi')
spyOn(defaultHtmlSequencerUi,'importStepsFromUrlHash')
defaultHtmlSequencerUi.onLoad()
defaultHtmlSequencerUi.selectNewStepUi()
defaultHtmlSequencerUi.addStepUi()
defaultHtmlSequencerUi.removeStepUi()
defaultHtmlSequencerUi.importStepsFromUrlHash()
})
it('load default ui', function() {
expect(defaultHtmlSequencerUi.onLoad).toHaveBeenCalled()
})
it('select step ui', function() {
expect(defaultHtmlSequencerUi.selectNewStepUi).toHaveBeenCalled()
})
it('add step ui', function() {
expect(defaultHtmlSequencerUi.addStepUi).toHaveBeenCalled()
})
it('remove step ui', function() {
expect(defaultHtmlSequencerUi.removeStepUi).toHaveBeenCalled()
})
it('import options from url', function() {
expect(defaultHtmlSequencerUi.importStepsFromUrlHash).toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,61 @@
var { JSDOM } = require('jsdom');
var DOM = new JSDOM(`<body></body>`);
global.document = DOM.window.document;
describe('Sequencer step HTML', function() {
var DefaultHtmlStepUi = require('../examples/lib/defaultHtmlStepUi')
var sequencer = require('../src/ImageSequencer')()
var defaultHtmlStepUi;
var step = 'brightness'
var options = {
name: "Brightness",
description: "Change the brightness of the image by given percent value"
}
// options = JSON.parse(options)
beforeEach(()=>{
defaultHtmlStepUi = new DefaultHtmlStepUi(sequencer)
spyOn(defaultHtmlStepUi,'getPreview')
spyOn(defaultHtmlStepUi,'onSetup')
spyOn(defaultHtmlStepUi,'onComplete')
spyOn(defaultHtmlStepUi,'onDraw')
spyOn(defaultHtmlStepUi,'onRemove')
spyOn(defaultHtmlStepUi,'notify')
defaultHtmlStepUi.getPreview()
defaultHtmlStepUi.onSetup(step,options)
defaultHtmlStepUi.onComplete(step)
defaultHtmlStepUi.onDraw(step)
defaultHtmlStepUi.onRemove(step)
defaultHtmlStepUi.notify('Step removed','remove-notification')
})
it('result preview ui', function() {
expect(defaultHtmlStepUi.getPreview).toHaveBeenCalled()
})
it('load initial setup ui', function() {
expect(defaultHtmlStepUi.onSetup).toHaveBeenCalledWith(step,options)
})
it('load completion ui', function() {
expect(defaultHtmlStepUi.onComplete).toHaveBeenCalledWith(step)
})
it('draw step ui', function() {
expect(defaultHtmlStepUi.onDraw).toHaveBeenCalledWith(step)
})
it('remove step ui', function() {
expect(defaultHtmlStepUi.onRemove).toHaveBeenCalledWith(step)
})
it('notification ui', function() {
expect(defaultHtmlStepUi.notify).toHaveBeenCalledWith('Step removed','remove-notification')
})
})

View File

@@ -0,0 +1,26 @@
describe('Preview UI HTML', function() {
var InsertPreview = require('../examples/lib/insertPreview')
var sequencer = require('../src/ImageSequencer')()
var insertPreview;
var options = { brightness: 50 }
beforeEach(()=>{
insertPreview = InsertPreview
spyOn(insertPreview,'generatePreview')
spyOn(insertPreview,'updatePreviews')
insertPreview.generatePreview('brightness',options,'src','selector')
insertPreview.updatePreviews('src','selector')
})
it('generate preview ui', function() {
expect(insertPreview.generatePreview).toHaveBeenCalledWith('brightness',options,'src','selector')
})
it('update preview ui', function() {
expect(insertPreview.updatePreviews).toHaveBeenCalledWith('src','selector')
})
})

View File

@@ -1,19 +1,19 @@
describe('Intermediate step HTML', function() {
var IntermediateHtmlStepUi = require('../../../examples/lib/intermediateHtmlStepUi');
var sequencer = require('../../../src/ImageSequencer')();
var IntermediateHtmlStepUi = require('../examples/lib/intermediateHtmlStepUi')
var sequencer = require('../src/ImageSequencer')()
var intermediateHtmlStepUi;
beforeEach(()=>{
intermediateHtmlStepUi = new IntermediateHtmlStepUi(sequencer);
intermediateHtmlStepUi = new IntermediateHtmlStepUi(sequencer)
spyOn(intermediateHtmlStepUi, 'insertStep');
spyOn(intermediateHtmlStepUi,'insertStep')
intermediateHtmlStepUi.insertStep();
});
intermediateHtmlStepUi.insertStep()
})
it('insert step ui', function() {
expect(intermediateHtmlStepUi.insertStep).toHaveBeenCalled();
});
expect(intermediateHtmlStepUi.insertStep).toHaveBeenCalled()
})
});
})

11
spec/support/jasmine.json Normal file
View File

@@ -0,0 +1,11 @@
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}

View File

@@ -1,40 +1,40 @@
describe('URL manipulation methods', function() {
var UrlHash = require('../../../examples/lib/urlHash');
var UrlHash = require('../examples/lib/urlHash')
var urlHash;
var params = {
module: 'brightness',
brightness: 50
};
}
beforeEach(()=>{
urlHash = UrlHash;
urlHash = UrlHash
spyOn(urlHash, 'getUrlHashParameters');
spyOn(urlHash, 'getUrlHashParameter');
spyOn(urlHash, 'setUrlHashParameters');
spyOn(urlHash, 'setUrlHashParameter');
spyOn(urlHash,'getUrlHashParameters')
spyOn(urlHash,'getUrlHashParameter')
spyOn(urlHash,'setUrlHashParameters')
spyOn(urlHash,'setUrlHashParameter')
urlHash.getUrlHashParameters();
urlHash.getUrlHashParameter('module');
urlHash.setUrlHashParameters(params);
urlHash.setUrlHashParameter('module', 'brightness');
});
urlHash.getUrlHashParameters()
urlHash.getUrlHashParameter('module')
urlHash.setUrlHashParameters(params)
urlHash.setUrlHashParameter('module','brightness')
})
it('gets url hash params from window hash', function() {
expect(urlHash.getUrlHashParameters).toHaveBeenCalled();
});
expect(urlHash.getUrlHashParameters).toHaveBeenCalled()
})
it('gets url hash param from params object', function() {
expect(urlHash.getUrlHashParameter).toHaveBeenCalledWith('module');
});
expect(urlHash.getUrlHashParameter).toHaveBeenCalledWith('module')
})
it('accepts param object and sets url hash params', function() {
expect(urlHash.setUrlHashParameters).toHaveBeenCalledWith(params);
});
expect(urlHash.setUrlHashParameters).toHaveBeenCalledWith(params)
})
it('accepts param key-value pair and sets url hash params', function() {
expect(urlHash.setUrlHashParameter).toHaveBeenCalledWith('module', 'brightness');
});
expect(urlHash.setUrlHashParameter).toHaveBeenCalledWith('module','brightness')
})
});
})

View File

@@ -1,5 +1,5 @@
// add steps to the sequencer
function AddStep(_sequencer, name, o) {
return require('./InsertStep')(_sequencer, -1, name, o);
return require('./InsertStep')(_sequencer,-1,name,o);
}
module.exports = AddStep;

View File

@@ -1,18 +1,18 @@
var fs = require('fs');
var fs = require('fs')
/*
* This function checks if the directory exists, if not it creates one on the given path
* Callback is called with argument error if an error is encountered
*/
function makedir(path, callback){
fs.access(path, function(err){
if(err) fs.mkdir(path, function(err){
if(err) callback(err);
callback();
function makedir(path,callback){
fs.access(path,function(err){
if(err) fs.mkdir(path,function(err){
if(err) callback(err);
callback();
});
else callback()
});
else callback();
});
}
};
// Takes an array of steps and checks if they are valid steps for the sequencer.
function validateSteps(steps, sequencer) {
@@ -37,9 +37,9 @@ function validateConfig(config_, options_) {
for (var input in options_) {
if (!config_[options_[input]]) {
console.error(
'\x1b[31m%s\x1b[0m',
"\x1b[31m%s\x1b[0m",
`Options Object does not have the required details "${
options_[input]
options_[input]
}" not specified. Fallback case activated`
);
return false;
@@ -52,7 +52,7 @@ function validateConfig(config_, options_) {
}
module.exports = exports = {
makedir: makedir,
validateSteps: validateSteps,
validateConfig: validateConfig
};
makedir: makedir,
validateSteps: validateSteps,
validateConfig: validateConfig
}

View File

@@ -2,7 +2,7 @@ var fs = require('fs');
var getDirectories = function(rootDir, cb) {
fs.readdir(rootDir, function(err, files) {
var dirs = [];
if (typeof (files) == 'undefined' || files.length == 0) {
if (typeof (files) == "undefined" || files.length == 0) {
cb(dirs);
return [];
}
@@ -21,15 +21,15 @@ var getDirectories = function(rootDir, cb) {
}
}
});
};
}
module.exports = function ExportBin(dir = './output/', ref, basic, filename) {
module.exports = function ExportBin(dir = "./output/", ref, basic, filename) {
// If user did not give an output filename so we can continue without doing anything
dir = (dir[dir.length - 1] == '/') ? dir : dir + '/';
dir = (dir[dir.length - 1] == "/") ? dir : dir + "/";
if (ref.options.inBrowser) return false;
fs.access(dir, function(err) {
if (err) console.error(err);
if (err) console.error(err)
});
if (filename && basic) {
var steps = ref.steps;
@@ -53,17 +53,17 @@ module.exports = function ExportBin(dir = './output/', ref, basic, filename) {
var datauri = steps.slice(-1)[0].output.src;
var ext = steps.slice(-1)[0].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(root + 'image' + '_' + (steps.length - 1) + '.' + ext, buffer, function() { });
fs.writeFile(root + "image" + "_" + (steps.length - 1) + "." + ext, buffer, function() { });
}
else {
for (var i in steps) {
var datauri = steps[i].output.src;
var ext = steps[i].output.format;
var buffer = require('data-uri-to-buffer')(datauri);
fs.writeFile(root + 'image' + '_' + i + '.' + ext, buffer, function() { });
fs.writeFile(root + "image" + "_" + i + "." + ext, buffer, function() { });
}
}
});
});
}
};
}

View File

@@ -1,19 +1,19 @@
function objTypeOf(object){
return Object.prototype.toString.call(object).split(' ')[1].slice(0, -1);
return Object.prototype.toString.call(object).split(" ")[1].slice(0,-1)
}
function getPrimitive(object){
return (objTypeOf(object) == 'Array') ? object[0] : object;
return (objTypeOf(object)=='Array')?object[0]:object;
}
function makeArray(input) {
return (objTypeOf(input) == 'Array') ? input : [input];
return (objTypeOf(input)=="Array")?input:[input];
}
function copy(a) {
if (!typeof(a) == 'object') return a;
if (objTypeOf(a) == 'Array') return a.slice();
if (objTypeOf(a) == 'Object') {
if (!typeof(a) == "object") return a;
if (objTypeOf(a) == "Array") return a.slice();
if (objTypeOf(a) == "Object") {
var b = {};
for (var v in a) {
b[v] = copy(a[v]);
@@ -23,80 +23,80 @@ function copy(a) {
return a;
}
function formatInput(args, format, images) {
function formatInput(args,format,images) {
var json_q = {};
var format_i = format;
if (format == '+')
if (format == "+")
format = ['string_a', 'o_object'];
else if (format == '-')
else if (format == "-")
format = ['number_a'];
else if (format == '^')
else if (format == "^")
format = ['number', 'string', 'o_object'];
else if (format == 'r')
else if (format == "r")
format = ['o_number'];
else if (format == 'l')
format = ['string', 'o_function'];
else if (format == "l")
format = ['string','o_function'];
if(format[format.length - 1] == 'o_object') {
if(objTypeOf(args[args.length - 1]) != 'Object')
if(format[format.length-1] == "o_object") {
if(objTypeOf(args[args.length-1]) != "Object")
args.push({});
}
else if (format[format.length - 1] == 'o_number') {
if(typeof(args[args.length - 1]) != 'number' && objTypeOf(args[0]) != 'Object')
else if (format[format.length-1] == "o_number") {
if(typeof(args[args.length-1]) != "number" && objTypeOf(args[0])!="Object")
args.push(1);
}
else if (format[format.length - 1] == 'o_function') {
if(objTypeOf(args[args.length - 1]) != 'Function' && objTypeOf(args[0]) != 'Object')
else if (format[format.length-1] == "o_function") {
if(objTypeOf(args[args.length-1]) != "Function" && objTypeOf(args[0])!="Object")
args.push(function(){});
}
if(args.length == format.length) {//making of arrays
for (var i in format) {
if (format[i].substr(format[i].length - 2, 2) == '_a')
if (format[i].substr(format[i].length-2,2)=="_a")
args[i] = makeArray(args[i]);
}
}
if (args.length == 1 ) {
if(format_i == 'r') json_q = {0:copy(args[0])};
else if(format_i == '-') {
json_q = [];
json_q = copy(args[0]);
if(format_i == "r") json_q = {0:copy(args[0])};
else if(format_i == "-") {
json_q=[];
json_q= copy(args[0]);
}
}
else if (format_i == 'r' ) {
else if (format_i == "r" ) {
for (var img in args[0]) json_q = {0:args[0]};
}
else if (format_i == 'l') {
else if (format_i == "l") {
json_q = {
image: args[0],
callback: args[1]
};
}
}
else {
json_q = [];
if(format_i == '+') {
for(var s in args[0]) {
json_q.push({
name: args[0][s],
o: args[1]
});
json_q = [];
if(format_i == "+") {
for(var s in args[0]) {
json_q.push({
name: args[0][s],
o: args[1]
});
}
}
}
if(format_i == '^') {
var size = this.steps.length;
var index = args[0];
index = (index == size) ? index : index % size;
if (index < 0) index += size + 1;
json_q.push({
index: index,
name: args[1],
o: args[2]
});
if(format_i == "^") {
var size = this.steps.length;
var index = args[0];
index = (index==size)?index:index%size;
if (index<0) index += size+1;
json_q.push({
index: index,
name: args[1],
o: args[2]
});
}
}

View File

@@ -1,31 +1,30 @@
if (typeof window !== 'undefined') { isBrowser = true; }
else { var isBrowser = false; }
if (typeof window !== 'undefined') { isBrowser = true }
else { var isBrowser = false }
require('./util/getStep.js');
ImageSequencer = function ImageSequencer(options) {
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
var sequencer = (this.name == 'ImageSequencer') ? this : this.sequencer;
var sequencer = (this.name == "ImageSequencer") ? this : this.sequencer;
options = options || {};
options.inBrowser = options.inBrowser === undefined ? isBrowser : options.inBrowser;
options.sequencerCounter = 0;
function objTypeOf(object) {
return Object.prototype.toString.call(object).split(' ')[1].slice(0, -1);
return Object.prototype.toString.call(object).split(" ")[1].slice(0, -1)
}
function log(color, msg) {
if (options.ui != 'none') {
if (options.ui != "none") {
if (arguments.length == 1) console.log(arguments[0]);
else if (arguments.length == 2) console.log(color, msg);
}
}
function copy(a) {
if (!typeof (a) == 'object') return a;
if (objTypeOf(a) == 'Array') return a.slice();
if (objTypeOf(a) == 'Object') {
var b = {};
if (!typeof (a) == "object") return a;
if (objTypeOf(a) == "Array") return a.slice();
if (objTypeOf(a) == "Object") {
var b = {};
for (var v in a) {
b[v] = copy(a[v]);
}
@@ -35,7 +34,7 @@ ImageSequencer = function ImageSequencer(options) {
}
function makeArray(input) {
return (objTypeOf(input) == 'Array') ? input : [input];
return (objTypeOf(input) == "Array") ? input : [input];
}
var image,
@@ -65,15 +64,15 @@ ImageSequencer = function ImageSequencer(options) {
// else if (options.imageUrl) loadImage(imageUrl);
function addSteps() {
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = [];
var json_q = {};
for (var arg in arguments) { args.push(copy(arguments[arg])); }
json_q = formatInput.call(this_, args, '+');
json_q = formatInput.call(this_, args, "+");
inputlog.push({ method: 'addSteps', json_q: copy(json_q) });
for (var j in json_q)
require('./AddStep')(this_, json_q[j].name, json_q[j].o);
inputlog.push({ method: "addSteps", json_q: copy(json_q) });
for (var j in json_q)
require("./AddStep")(this_, json_q[j].name, json_q[j].o);
return this;
}
@@ -88,58 +87,58 @@ ImageSequencer = function ImageSequencer(options) {
//tell the UI a step has been removed
}
function removeSteps() {
function removeSteps(index) {
var indices;
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this_, args, '-');
inputlog.push({ method: 'removeSteps', json_q: copy(json_q) });
var json_q = formatInput.call(this_, args, "-");
inputlog.push({ method: "removeSteps", json_q: copy(json_q) });
indices = json_q.sort(function(a, b) { return b - a; });
for (var i in indices)
removeStep(this_, indices[i]);
indices = json_q.sort(function(a, b) { return b - a });
for (var i in indices)
removeStep(this_, indices[i]);
return this;
}
function insertSteps() {
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var args = [];
function insertSteps(image, index, name, o) {
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = []
for (var arg in arguments) args.push(arguments[arg]);
var json_q = formatInput.call(this_, args, '^');
inputlog.push({ method: 'insertSteps', json_q: copy(json_q) });
var json_q = formatInput.call(this_, args, "^");
inputlog.push({ method: "insertSteps", json_q: copy(json_q) });
var details = json_q;
details = details.sort(function(a, b) { return b.index - a.index; });
for (var i in details)
require('./InsertStep')(this_, details[i].index, details[i].name, details[i].o);
var details = json_q;
details = details.sort(function(a, b) { return b.index - a.index });
for (var i in details)
require("./InsertStep")(this_, details[i].index, details[i].name, details[i].o);
return this;
}
// Config is an object which contains the runtime configuration like progress bar
// information and index from which the sequencer should run
function run(config) {
function run(config, t_image, t_from) {
var progressObj, index = 0;
config = config || { mode: 'no-arg' };
if (config.index) index = config.index;
if (config.mode != 'no-arg' && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
if (config.mode != "no-arg" && typeof config != 'function') {
if (config.progressObj) progressObj = config.progressObj;
delete arguments['0'];
}
var this_ = (this.name == 'ImageSequencer') ? this : this.sequencer;
var this_ = (this.name == "ImageSequencer") ? this : this.sequencer;
var args = [];
for (var arg in arguments) args.push(copy(arguments[arg]));
var callback = function() { };
for (var arg in args)
if (objTypeOf(args[arg]) == 'Function')
if (objTypeOf(args[arg]) == "Function")
callback = args.splice(arg, 1)[0]; //callback is formed
var json_q = formatInput.call(this_, args, 'r');
var json_q = formatInput.call(this_, args, "r");
require('./Run')(this_, json_q, callback, index, progressObj);
@@ -148,19 +147,19 @@ ImageSequencer = function ImageSequencer(options) {
function loadImages() {
var args = [];
var prevSteps = this.getSteps().slice(1).map(step=>step.options.name);
var prevSteps = this.getSteps().slice(1).map(step=>step.options.name)
var sequencer = this;
sequencer.image = arguments[0];
for (var arg in arguments) args.push(copy(arguments[arg]));
var json_q = formatInput.call(this, args, 'l');
if(this.getSteps().length != 0){
var json_q = formatInput.call(this, args, "l");
if(this.getSteps().length!=0){
this.options.sequencerCounter = 0;
inputlog = [];
this.steps = [];
}
inputlog.push({ method: 'loadImages', json_q: copy(json_q) });
inputlog.push({ method: "loadImages", json_q: copy(json_q) });
var ret = {
name: 'ImageSequencer Wrapper',
name: "ImageSequencer Wrapper",
sequencer: this,
addSteps: this.addSteps,
removeSteps: this.removeSteps,
@@ -170,16 +169,16 @@ ImageSequencer = function ImageSequencer(options) {
setUI: this.setUI
};
function loadPrevSteps(ref){
if(prevSteps.length != 0){
ref.addSteps(prevSteps);
prevSteps = [];
if(prevSteps.length!=0){
ref.addSteps(prevSteps)
prevSteps=[];
}
}
require('./ui/LoadImage')(sequencer, 'image', json_q.image, function() {
require('./ui/LoadImage')(sequencer, "image", json_q.image, function() {
loadPrevSteps(sequencer);
json_q.callback.call(ret);
});
}
function replaceImage(selector, steps, options) {
@@ -199,11 +198,11 @@ ImageSequencer = function ImageSequencer(options) {
var exportBin = function(dir, basic, filename) {
return require('./ExportBin')(dir, this, basic, filename);
};
}
function modulesInfo(name) {
var modulesdata = {};
if (name == 'load-image') return {};
var modulesdata = {}
if (name == "load-image") return {};
if (arguments.length == 0) {
for (var modulename in this.modules) {
modulesdata[modulename] = modules[modulename][1];
@@ -213,15 +212,133 @@ ImageSequencer = function ImageSequencer(options) {
}
}
else {
if (modules[name]){
modulesdata = modules[name][1];
}
if (modules[name]){
modulesdata = modules[name][1];
}
else
modulesdata = { 'inputs': sequences[name]['options'] };
}
return modulesdata;
}
// Genates a CLI string for the current sequence
function toCliString() {
var cliStringSteps = `"`, cliOptions = {};
for (var step in this.steps) {
var name = (typeof this.steps[step].options !== "undefined")? this.steps[step].options.name : this.steps[step].name
if (name !== "load-image"){
cliStringSteps += `${name} `;
}
for (var inp in modulesInfo(name).inputs) {
cliOptions[inp] = this.steps[step].options[inp];
}
}
cliStringSteps = cliStringSteps.substr(0, cliStringSteps.length - 1) + `"`;
return `sequencer -i [PATH] -s ${cliStringSteps} -d '${JSON.stringify(cliOptions)}'`
}
// Strigifies the current sequence
function toString(step) {
if (step) {
return stepToString(step);
} else {
return copy(this.steps.map(stepToString).slice(1).join(','));
}
}
// Stringifies one step of the sequence
function stepToString(step) {
var arg = (step.name)?step.name:step.options.name;
let inputs = modulesInfo(arg).inputs || {}, op = {};
for (let input in inputs) {
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${arg}{${configurations}}`;
}
// exports the current sequence as an array of JSON steps
function toJSON() {
return this.stringToJSON(this.toString());
}
// Coverts stringified sequence into an array of JSON steps
function stringToJSON(str) {
let steps;
if (str.includes(','))
steps = str.split(',');
else
steps = [str];
return steps.map(stringToJSONstep);
}
// Converts one stringified step into JSON
function stringToJSONstep(str) {
var bracesStrings;
if (str.includes('{'))
if (str.includes('(') && str.indexOf('(') < str.indexOf('{'))
bracesStrings = ['(', ')'];
else
bracesStrings = ['{', '}'];
else
bracesStrings = ['(', ')'];
if (str.indexOf(bracesStrings[0]) === -1) { // if there are no settings specified
var moduleName = str.substr(0);
stepSettings = "";
} else {
var moduleName = str.substr(0, str.indexOf(bracesStrings[0]));
stepSettings = str.slice(str.indexOf(bracesStrings[0]) + 1, -1);
}
stepSettings = stepSettings.split('|').reduce(function formatSettings(accumulator, current, i) {
var settingName = current.substr(0, current.indexOf(':')),
settingValue = current.substr(current.indexOf(':') + 1);
settingValue = settingValue.replace(/^\(/, '').replace(/\)$/, ''); // strip () at start/end
settingValue = settingValue.replace(/^\{/, '').replace(/\}$/, ''); // strip {} at start/end
settingValue = decodeURIComponent(settingValue);
current = [
settingName,
settingValue
];
if (!!settingName) accumulator[settingName] = settingValue;
return accumulator;
}, {});
return {
name: moduleName,
options: stepSettings
}
}
// imports a string into the sequencer steps
function importString(str) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
var stepsFromString = stringToJSON(str);
stepsFromString.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// imports a array of JSON steps into the sequencer steps
function importJSON(obj) {
let sequencer = this;
if (this.name != "ImageSequencer")
sequencer = this.sequencer;
obj.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
function loadNewModule(name, options) {
if (!options) {
@@ -254,12 +371,12 @@ ImageSequencer = function ImageSequencer(options) {
return;
}
var mods = fs.readFileSync('./src/Modules.js').toString();
mods = mods.substr(0, mods.length - 1) + ' \'' + name + '\': require(\'' + path + '\'),\n}';
mods = mods.substr(0, mods.length - 1) + " '" + name + "': require('" + path + "'),\n}";
fs.writeFileSync('./src/Modules.js', mods);
}
function saveSequence(name, sequenceString) { // 4. save sequence
const sequence = str.stringToJSON(sequenceString);
function saveSequence(name, sequenceString) {
const sequence = stringToJSON(sequenceString);
// Save the given sequence string as a module
if (options.inBrowser) {
// Inside the browser we save the meta-modules using the Web Storage API
@@ -284,10 +401,9 @@ ImageSequencer = function ImageSequencer(options) {
this.sequences = require('./SavedSequences.json');
}
return {
//literals and objects
name: 'ImageSequencer',
name: "ImageSequencer",
options: options,
inputlog: inputlog,
modules: modules,
@@ -307,17 +423,14 @@ ImageSequencer = function ImageSequencer(options) {
setUI: setUI,
exportBin: exportBin,
modulesInfo: modulesInfo,
toCliString: str.toCliString,
detectStringSyntax: str.detectStringSyntax,
parseStringSyntax: str.parseStringSyntax,
stringToSteps: str.stringToSteps,
toString: str.toString,
stepToString: str.stepToString,
toJSON: str.toJSON,
stringToJSON: str.stringToJSON,
stringToJSONstep: str.stringToJSONstep,
importString: str.importString,
importJSON: str.importJSON,
toCliString: toCliString,
toString: toString,
stepToString: stepToString,
toJSON: toJSON,
stringToJSON: stringToJSON,
stringToJSONstep: stringToJSONstep,
importString: importString,
importJSON: importJSON,
loadNewModule: loadNewModule,
saveNewModule: saveNewModule,
createMetaModule: require('./util/createMetaModule'),
@@ -331,7 +444,7 @@ ImageSequencer = function ImageSequencer(options) {
copy: copy,
setInputStep: require('./ui/SetInputStep')(sequencer)
};
}
};
}
module.exports = ImageSequencer;

View File

@@ -6,9 +6,6 @@ function InsertStep(ref, index, name, o) {
return ref.importJSON(ref.sequences[name]);
}
if (ref.detectStringSyntax(name)) {
return ref.stringToSteps(name);
}
function insertStep(index, name, o_) {
if (ref.modules[name]) var moduleInfo = ref.modules[name][1];
@@ -21,17 +18,15 @@ function InsertStep(ref, index, name, o) {
o.number = ref.options.sequencerCounter++; //Gives a Unique ID to each step
o.name = o_.name || name || moduleInfo.name;
o.description = o_.description || moduleInfo.description;
o.moduleInfo = o_.moduleInfo || moduleInfo;
o.selector = o_.selector || 'ismod-' + name;
o.container = o_.container || ref.options.selector;
o.inBrowser = ref.options.inBrowser;
o.useWasm = (ref.options.useWasm === false) ? false : true;
if (index == -1) index = ref.steps.length;
o.step = {
name: o.name,
description: o.description,
moduleInfo: o.moduleInfo,
ID: o.number,
inBrowser: ref.options.inBrowser,
ui: ref.options.ui,
@@ -45,7 +40,7 @@ function InsertStep(ref, index, name, o) {
let step = stepsArray[i];
ref.insertSteps(index + Number.parseInt(i), step['name'], step['options']);
}
};
}
// Tell UI that a step has been set up.
o = o || {};

View File

@@ -5,13 +5,10 @@ module.exports = {
'add-qr': require('./modules/AddQR'),
'average': require('./modules/Average'),
'blend': require('./modules/Blend'),
'blob-analysis': require('./modules/BlobAnalysis'),
'blur': require('./modules/Blur'),
'brightness': require('./modules/Brightness'),
'canvas-resize': require('./modules/CanvasResize'),
'channel': require('./modules/Channel'),
'colorbar': require('./modules/Colorbar'),
'color-temperature': require('./modules/ColorTemperature'),
'colormap': require('./modules/Colormap'),
'contrast': require('./modules/Contrast'),
'convolution': require('./modules/Convolution'),
@@ -27,23 +24,18 @@ module.exports = {
'histogram': require('./modules/Histogram'),
'gamma-correction': require('./modules/GammaCorrection'),
'gradient': require('./modules/Gradient'),
'grid-overlay': require('./modules/GridOverlay'),
'import-image': require('./modules/ImportImage'),
'minify-image': require('./modules/MinifyImage'),
'invert': require('image-sequencer-invert'),
'matcher': require('./modules/Matcher'),
'ndvi': require('./modules/Ndvi'),
'ndvi-colormap': require('./modules/NdviColormap'),
'noise-reduction': require('./modules/NoiseReduction'),
'overlay': require('./modules/Overlay'),
'paint-bucket': require('./modules/PaintBucket'),
'replace-color': require('./modules/ReplaceColor'),
'overlay': require('./modules/Overlay'),
'replace-color':require('./modules/ReplaceColor'),
'resize': require('./modules/Resize'),
'rotate': require('./modules/Rotate'),
'saturation': require('./modules/Saturation'),
'text-overlay': require('./modules/TextOverlay'),
'threshold': require('./modules/Threshold'),
'tint': require('./modules/Tint'),
'webgl-distort': require('./modules/WebglDistort'),
'white-balance': require('./modules/WhiteBalance')
};
'color-temperature': require('./modules/ColorTemperature')
}

View File

@@ -1,6 +1,6 @@
// Uses a given image as input and replaces it with the output.
// Works only in the browser.
function ReplaceImage(ref, selector, steps, options) {
function ReplaceImage(ref,selector,steps,options) {
if(!ref.options.inBrowser) return false; // This isn't for Node.js
var tempSequencer = ImageSequencer({ui: false});
var this_ = ref;
@@ -26,27 +26,23 @@ function ReplaceImage(ref, selector, steps, options) {
// https://github.com/publiclab/image-sequencer/issues/241
// https://stackoverflow.com/a/20048852/1116657
var raw = '';
var i, j, subArray, chunk = 5000;
for (i = 0, j = arr.length; i < j; i += chunk) {
subArray = arr.subarray(i, i + chunk);
var i,j,subArray,chunk = 5000;
for (i=0,j=arr.length; i<j; i+=chunk) {
subArray = arr.subarray(i,i+chunk);
raw += String.fromCharCode.apply(null, subArray);
}
var base64 = btoa(raw);
var dataURL = 'data:image/' + ext + ';base64,' + base64;
var dataURL="data:image/"+ext+";base64," + base64;
make(dataURL);
};
if(url.substr(0, 11).toLowerCase() != 'data:image/') xmlHTTP.send();
if(url.substr(0,11).toLowerCase()!="data:image/") xmlHTTP.send();
else make(url);
function make(url) {
tempSequencer.loadImage(url, function(){
// this.addSteps(steps).run({stop:function(){}},function(out){
var sequence = this.addSteps(steps);
if (ref.detectStringSyntax(steps))
sequence = this.stringToSteps(steps);
sequence.run({stop:function(){}}, function(out){
this.addSteps(steps).run({stop:function(){}},function(out){
img.src = out;
});
});
@@ -54,8 +50,8 @@ function ReplaceImage(ref, selector, steps, options) {
}
for (var i = 0; i < images.length; i++) {
replaceImage(images[i], steps);
if (i == images.length - 1)
replaceImage(images[i],steps);
if (i == images.length-1)
options.callback();
}
}

View File

@@ -5,7 +5,7 @@ function Run(ref, json_q, callback, ind, progressObj) {
function drawStep(drawarray, pos) {
if (pos == drawarray.length && drawarray[pos - 1] !== undefined) {
if (ref.objTypeOf(callback) == 'Function' && ref.steps.slice(-1)[0].output) {
if (ref.objTypeOf(callback) == "Function" && ref.steps.slice(-1)[0].output) {
var steps = ref.steps;
var out = steps[steps.length - 1].output.src;
callback(out);
@@ -25,7 +25,7 @@ function Run(ref, json_q, callback, ind, progressObj) {
};
step.getIndex = function getIndex() {
return i;
};
}
for (var util in getStepUtils) {
if (getStepUtils.hasOwnProperty(util)) {
@@ -43,7 +43,7 @@ function Run(ref, json_q, callback, ind, progressObj) {
inputForNextStep,
function onEachStep() {
// This output is accessible by UI
// This output is accessible by UI
ref.steps[i].options.step.output = ref.steps[i].output.src;
// Tell UI that step has been drawn.
@@ -58,26 +58,26 @@ function Run(ref, json_q, callback, ind, progressObj) {
function drawSteps(json_q) {
var drawarray = [],
no_steps = ref.steps.length,
init = json_q[0];
for (var i = 0; i < no_steps - init; i++) {
drawarray.push({i: init + i });
}
no_steps = ref.steps.length,
init = json_q[0];
for (var i = 0; i < no_steps - init; i++) {
drawarray.push({i: init + i });
}
drawStep(drawarray, ind);
}
function filter(json_q) {
if (json_q[0] == 0 && ref.steps.length == 1)
delete json_q[0];
else if (json_q[0] == 0) json_q[0]++;
var prevstep = ref.steps[json_q[0] - 1];
while (
typeof prevstep == 'undefined' ||
typeof prevstep.output == 'undefined'
) {
prevstep = ref.steps[--json_q[0] - 1];
}
if (json_q[0] == 0 && ref.steps.length == 1)
delete json_q[0];
else if (json_q[0] == 0) json_q[0]++;
var prevstep = ref.steps[json_q[0] - 1];
while (
typeof prevstep == "undefined" ||
typeof prevstep.output == "undefined"
) {
prevstep = ref.steps[--json_q[0] - 1];
}
return json_q;
}

View File

@@ -5,10 +5,10 @@ const dataUriToBuffer = require('data-uri-to-buffer');
const savePixels = require('save-pixels');
module.exports = function(input) {
input.getPixels = getPixels;
input.pixelManipulation = pixelManipulation;
input.lodash = lodash;
input.dataUriToBuffer = dataUriToBuffer;
input.savePixels = savePixels;
return input;
};
input.getPixels = getPixels;
input.pixelManipulation = pixelManipulation;
input.lodash = lodash;
input.dataUriToBuffer = dataUriToBuffer;
input.savePixels = savePixels;
return input;
}

View File

@@ -1,159 +0,0 @@
module.exports = function(steps, modulesInfo, addSteps, copy) {
// Genates a CLI string for the current sequence
function toCliString() {
var cliStringSteps = '"', cliOptions = {};
for (var step in this.steps) {
var name = (typeof this.steps[step].options !== 'undefined') ? this.steps[step].options.name : this.steps[step].name;
if (name !== 'load-image'){
cliStringSteps += `${name} `;
}
for (var inp in modulesInfo(name).inputs) {
cliOptions[inp] = this.steps[step].options[inp];
}
}
cliStringSteps = cliStringSteps.substr(0, cliStringSteps.length - 1) + '"';
return `sequencer -i [PATH] -s ${cliStringSteps} -d '${JSON.stringify(cliOptions)}'`;
}
// Checks if input is a string of comma separated module names
function detectStringSyntax(str) {
let result = (str.includes(',') || str.includes('{')) ? true : false;
return result;
}
// Parses input string and returns array of module names
function parseStringSyntax(str) {
let stringifiedNames = str.replace(/\s/g, '');
let moduleNames = stringifiedNames.split(',');
return moduleNames;
}
// imports string of comma separated module names to sequencer steps
function stringToSteps(str) {
let sequencer = this;
let names = [];
if (this.name != 'ImageSequencer')
sequencer = this.sequencer;
if (detectStringSyntax(str))
names = stringToJSON(str);
names.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// Strigifies the current sequence
function toString(step) {
if (step) {
return stepToString(step);
} else {
return copy(this.steps.map(stepToString).slice(1).join(','));
}
}
// Stringifies one step of the sequence
function stepToString(step) {
var arg = (step.name) ? step.name : step.options.name;
let inputs = modulesInfo(arg).inputs || {}, op = {};
for (let input in inputs) {
if (!!step.options[input] && step.options[input] != inputs[input].default) {
op[input] = step.options[input];
op[input] = encodeURIComponent(op[input]);
}
}
var configurations = Object.keys(op).map(key => key + ':' + op[key]).join('|');
return `${arg}{${configurations}}`;
}
// exports the current sequence as an array of JSON steps
function toJSON() {
return this.stringToJSON(this.toString());
}
// Coverts stringified sequence into an array of JSON steps
function stringToJSON(str) {
let steps;
if (detectStringSyntax(str))
steps = parseStringSyntax(str);
else
steps = [str];
return steps.map(stringToJSONstep);
}
// Converts one stringified step into JSON
function stringToJSONstep(str) {
var bracesStrings;
if (str.includes('{'))
if (str.includes('(') && str.indexOf('(') < str.indexOf('{'))
bracesStrings = ['(', ')'];
else
bracesStrings = ['{', '}'];
else
bracesStrings = ['(', ')'];
if (str.indexOf(bracesStrings[0]) === -1) { // if there are no settings specified
var moduleName = str.substr(0);
stepSettings = '';
} else {
var moduleName = str.substr(0, str.indexOf(bracesStrings[0]));
stepSettings = str.slice(str.indexOf(bracesStrings[0]) + 1, -1);
}
stepSettings = stepSettings.split('|').reduce(function formatSettings(accumulator, current, i) {
var settingName = current.substr(0, current.indexOf(':')),
settingValue = current.substr(current.indexOf(':') + 1);
settingValue = settingValue.replace(/^\(/, ''); // strip () at start/end
settingValue = settingValue.replace(/^\{/, '').replace(/\}$/, ''); // strip {} at start/end
settingValue = decodeURIComponent(settingValue);
current = [
settingName,
settingValue
];
if (settingName) accumulator[settingName] = settingValue;
return accumulator;
}, {});
return {
name: moduleName,
options: stepSettings
};
}
// imports a string into the sequencer steps
function importString(str) {
let sequencer = this;
if (this.name != 'ImageSequencer')
sequencer = this.sequencer;
var stepsFromString = stringToJSON(str);
stepsFromString.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
// imports a array of JSON steps into the sequencer steps
function importJSON(obj) {
let sequencer = this;
if (this.name != 'ImageSequencer')
sequencer = this.sequencer;
obj.forEach(function eachStep(stepObj) {
sequencer.addSteps(stepObj.name, stepObj.options);
});
}
return {
toCliString: toCliString,
detectStringSyntax: detectStringSyntax,
parseStringSyntax: parseStringSyntax,
stringToSteps: stringToSteps,
toString: toString,
stepToString: stepToString,
toJSON: toJSON,
stringToJSON: stringToJSON,
stringToJSONstep: stringToJSONstep,
importString: importString,
importJSON: importJSON
};
};

View File

@@ -1,17 +1,17 @@
var childProcess = require('child_process');
var childProcess = require('child_process')
var Spinner = require('ora');
module.exports = function (program, sequencer) {
console.log(
'\x1b[33m%s\x1b[0m',
'Please wait while your Module is being Installed...\nThis may take a while!'
);
console.log(
"\x1b[33m%s\x1b[0m",
"Please wait while your Module is being Installed...\nThis may take a while!"
);
var params = program.installModule.split(' ');
var spinner = Spinner('Now Installing...').start();
childProcess.execSync(`npm i ${params[1]}`);
sequencer.saveNewModule(params[0], params[1]);
sequencer.loadNewModule(params[0], require(params[1]));
spinner.stop();
console.log('\x1b[32m%s\x1b[0m', 'Your module was installed successfully!!');
};
var params = program.installModule.split(' ');
var spinner = Spinner("Now Installing...").start();
childProcess.execSync(`npm i ${params[1]}`)
sequencer.saveNewModule(params[0], params[1]);
sequencer.loadNewModule(params[0], require(params[1]));
spinner.stop();
console.log("\x1b[32m%s\x1b[0m", "Your module was installed successfully!!");
}

View File

@@ -1,7 +1,7 @@
module.exports = function (program, sequencer) {
var params = program.saveSequence.split(' ');
sequencer.saveSequence(params[0], params[1]);
console.log('\x1b[32m', 'Your sequence was saved successfully!!');
var params = program.saveSequence.split(' ');
sequencer.saveSequence(params[0], params[1]);
console.log("\x1b[32m", "Your sequence was saved successfully!!");
};
}

View File

@@ -1,13 +1,13 @@
var Spinner = require('ora');
var readlineSync = require('readline-sync');
var utils = require('../CliUtils');
var utils = require('../CliUtils')
module.exports = function (program, sequencer, outputFilename) {
utils.makedir(program.output, () => {
console.log('Files will be exported to "' + program.output + '"');
if (program.basic)
console.log('Basic mode is enabled, outputting only final image');
console.log("Basic mode is enabled, outputting only final image");
// Iterate through the steps and retrieve their inputs.
program.step.forEach(function(step) {
@@ -15,7 +15,7 @@ module.exports = function (program, sequencer, outputFilename) {
// If inputs exists, print to console.
if (Object.keys(options).length) {
console.log('[' + step + ']: Inputs');
console.log("[" + step + "]: Inputs");
}
// If inputs exists, print them out with descriptions.
@@ -23,9 +23,9 @@ module.exports = function (program, sequencer, outputFilename) {
// The array below creates a variable number of spaces. This is done with (length + 1).
// The extra 4 that makes it (length + 5) is to account for the []: characters
console.log(
new Array(step.length + 5).join(' ') +
new Array(step.length + 5).join(" ") +
input +
': ' +
": " +
options[input].desc
);
});
@@ -33,18 +33,18 @@ module.exports = function (program, sequencer, outputFilename) {
if (program.config) {
try {
var config = JSON.parse(program.config);
console.log('The parsed options object: ', config);
console.log(`The parsed options object: `, config);
} catch (e) {
console.error(
'\x1b[31m%s\x1b[0m',
'Options(Config) is not a not valid JSON Fallback activate'
"\x1b[31m%s\x1b[0m",
`Options(Config) is not a not valid JSON Fallback activate`
);
program.config = false;
console.log(e);
}
}
if (program.config && utils.validateConfig(config, options)) {
console.log('Now using Options object');
console.log("Now using Options object");
Object.keys(options).forEach(function(input) {
options[input] = config[input];
});
@@ -52,15 +52,15 @@ module.exports = function (program, sequencer, outputFilename) {
// If inputs exist, iterate through them and prompt for values.
Object.keys(options).forEach(function(input) {
var value = readlineSync.question(
'[' +
"[" +
step +
']: Enter a value for ' +
"]: Enter a value for " +
input +
' (' +
" (" +
options[input].type +
', default: ' +
", default: " +
options[input].default +
'): '
"): "
);
options[input] = value;
});
@@ -71,7 +71,7 @@ module.exports = function (program, sequencer, outputFilename) {
var spinnerObj = { succeed: () => { }, stop: () => { } };
if (!process.env.TEST)
spinnerObj = Spinner('Your Image is being processed..').start();
spinnerObj = Spinner("Your Image is being processed..").start();
// Run the sequencer.
sequencer.run({ progressObj: spinnerObj }, function() {
@@ -81,8 +81,8 @@ module.exports = function (program, sequencer, outputFilename) {
//check if spinner was not overriden stop it
if (!spinnerObj.overrideFlag) {
spinnerObj.succeed();
console.log('\nDone!!');
console.log(`\nDone!!`);
}
});
});
};
}

View File

@@ -1,52 +1,51 @@
module.exports = function AddQR(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.size = options.size || defaults.size;
options.qrCodeString = options.qrCodeString || 'https://github.com/publiclab/image-sequencer';
var output;
getPixels = require('get-pixels');
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.size = options.size || defaults.size;
options.qrCodeString = options.qrCodeString || "https://github.com/publiclab/image-sequencer";
var output;
getPixels = require('get-pixels');
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
return getPixels(input.src, function(err, oldPixels) {
function changePixel(r, g, b, a) {
return [r, g, b, a];
}
return getPixels(input.src, function (err, oldPixels) {
function changePixel(r, g, b, a) {
return [r, g, b, a];
}
function extraManipulation(pixels,generateOutput) {
if (err) {
console.log(err);
return;
}
require('./QR')(options, pixels, oldPixels, generateOutput);
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
function extraManipulation(pixels, generateOutput) {
if (err) {
console.log(err);
return;
}
require('./QR')(options, pixels, oldPixels, generateOutput);
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
})
}
return {
options: options,
draw: draw,
output: output,
ui: options.step.ui,
changePixel: changePixel,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
UI: UI
}
}

View File

@@ -1,44 +1,48 @@
module.exports = exports = function (options, pixels, oldPixels, callback) {
const pixelSetter = require('../../util/pixelSetter.js');
var QRCode = require('qrcode')
QRCode.toDataURL(options.qrCodeString, function (err, url) {
var getPixels = require("get-pixels");
getPixels(url, function (err, qrPixels) {
if (err) {
console.log("Bad image path", image);
}
var QRCode = require('qrcode');
QRCode.toDataURL(options.qrCodeString, function (err, url) {
var getPixels = require('get-pixels');
getPixels(url, function (err, qrPixels) {
if (err) {
console.log('Bad image path', image);
}
var imagejs = require('imagejs');
var bitmap = new imagejs.Bitmap({ width: qrPixels.shape[0], height: qrPixels.shape[1] });
bitmap._data.data = qrPixels.data;
var resized = bitmap.resize({
width: options.size, height: options.size,
algorithm: "bicubicInterpolation"
});
var imagejs = require('imagejs');
var bitmap = new imagejs.Bitmap({ width: qrPixels.shape[0], height: qrPixels.shape[1] });
bitmap._data.data = qrPixels.data;
var resized = bitmap.resize({
width: options.size, height: options.size,
algorithm: 'bicubicInterpolation'
});
qrPixels.data = resized._data.data;
qrPixels.shape = [options.size, options.size, 4];
qrPixels.stride[1] = 4 * options.size;
qrPixels.data = resized._data.data;
qrPixels.shape = [options.size, options.size, 4];
qrPixels.stride[1] = 4 * options.size;
var width = oldPixels.shape[0],
height = oldPixels.shape[1];
var xe = width - options.size,
ye = height - options.size;
for (var m = 0; m < width; m++) {
for (var n = 0; n < height; n++) {
if (m >= xe && n >= ye) {
pixels.set(m, n, 0, qrPixels.get(m - xe, n - ye, 0))
pixels.set(m, n, 1, qrPixels.get(m - xe, n - ye, 1))
pixels.set(m, n, 2, qrPixels.get(m - xe, n - ye, 2))
pixels.set(m, n, 3, qrPixels.get(m - xe, n - ye, 3))
}
var width = oldPixels.shape[0],
height = oldPixels.shape[1];
var xe = width - options.size,
ye = height - options.size;
for (var m = 0; m < width; m++) {
for (var n = 0; n < height; n++) {
if (m >= xe && n >= ye) {
pixelSetter(m, n, [qrPixels.get(m - xe, n - ye, 0), qrPixels.get(m - xe, n - ye, 1), qrPixels.get(m - xe, n - ye, 2), qrPixels.get(m - xe, n - ye, 3)], pixels);
}
else {
pixels.set(m, n, 0, oldPixels.get(m, n, 0))
pixels.set(m, n, 1, oldPixels.get(m, n, 1))
pixels.set(m, n, 2, oldPixels.get(m, n, 2))
pixels.set(m, n, 3, oldPixels.get(m, n, 3))
}
else {
pixelSetter(m, n, [qrPixels.get(m, n, 0), qrPixels.get(m, n, 1), qrPixels.get(m, n, 2), qrPixels.get(m, n, 3)], pixels);
}
}
}
callback();
}
}
callback();
});
});
};
})
})
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "add-qr",
"name": "Add QR",
"description": "Adds QR corresponding to the given string",
"url": "https://github.com/publiclab/image-sequencer/tree/master/MODULES.md",
"inputs": {

View File

@@ -3,74 +3,72 @@
*/
module.exports = function Average(options, UI) {
var output;
var output;
options.step.metadata = options.step.metadata || {};
options.step.metadata = options.step.metadata || {};
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
// do the averaging
function extraManipulation(pixels) {
var i = 0, sum = [0, 0, 0, 0];
while (i < pixels.data.length) {
sum[0] += pixels.data[i++];
sum[1] += pixels.data[i++];
sum[2] += pixels.data[i++];
sum[3] += pixels.data[i++];
}
// do the averaging
function extraManipulation(pixels) {
var i = 0, sum = [0, 0, 0, 0];
while (i < pixels.data.length) {
sum[0] += pixels.data[i++];
sum[1] += pixels.data[i++];
sum[2] += pixels.data[i++];
sum[3] += pixels.data[i++];
}
let divisor = pixels.data.length / 4;
let divisor = pixels.data.length / 4;
sum[0] = Math.floor(sum[0] / divisor);
sum[1] = Math.floor(sum[1] / divisor);
sum[2] = Math.floor(sum[2] / divisor);
sum[3] = Math.floor(sum[3] / divisor);
sum[0] = Math.floor(sum[0] / divisor);
sum[1] = Math.floor(sum[1] / divisor);
sum[2] = Math.floor(sum[2] / divisor);
sum[3] = Math.floor(sum[3] / divisor);
i = 0;
while (i < pixels.data.length) {
pixels.data[i++] = sum[0];
pixels.data[i++] = sum[1];
pixels.data[i++] = sum[2];
pixels.data[i++] = sum[3];
}
i = 0
while (i < pixels.data.length) {
pixels.data[i++] = sum[0];
pixels.data[i++] = sum[1];
pixels.data[i++] = sum[2];
pixels.data[i++] = sum[3];
}
// report back and store average in metadata:
options.step.metadata.averages = sum;
// report back and store average in metadata:
options.step.metadata.averages = sum;
// TODO: refactor into a new "display()" method as per https://github.com/publiclab/image-sequencer/issues/242
if (options.step.inBrowser && options.step.ui) $(options.step.ui).find('.details').append("<p><b>Averages</b> (r, g, b, a): " + sum.join(', ') + "</p>");
return pixels;
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = {
src: datauri,
format: mimetype
};
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
// TODO: refactor into a new "display()" method as per https://github.com/publiclab/image-sequencer/issues/242
if (options.step.inBrowser && options.step.ui) $(options.step.ui).find('.details').append('<p><b>Averages</b> (r, g, b, a): ' + sum.join(', ') + '</p>');
return pixels;
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = {
src: datauri,
format: mimetype
};
return {
options: options,
draw: draw,
output: output,
UI: UI
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "average",
"name": "Average",
"description": "Average all pixel color",
"inputs": {
},

View File

@@ -1,77 +1,75 @@
module.exports = function Dynamic(options, UI, util) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.func = options.func || defaults.blend;
options.offset = options.offset || defaults.offset;
options.func = options.func || defaults.blend;
options.offset = options.offset || defaults.offset;
var output;
var output;
// This function is called on every draw.
function draw(input, callback, progressObj) {
// This function is called on every draw.
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
// convert to runnable code:
if (typeof options.func === 'string') eval('options.func = ' + options.func);
// convert to runnable code:
if (typeof options.func === "string") eval('options.func = ' + options.func);
var getPixels = require('get-pixels');
var getPixels = require('get-pixels');
// convert offset as string to int
if (typeof options.offset === 'string') options.offset = parseInt(options.offset);
// convert offset as string to int
if (typeof options.offset === "string") options.offset = parseInt(options.offset);
// save first image's pixels
var priorStep = this.getStep(options.offset);
// save first image's pixels
var priorStep = this.getStep(options.offset);
if (priorStep.output === undefined) {
this.output = input;
UI.notify('Offset Unavailable', 'offset-notification');
callback();
if (priorStep.output === undefined) {
this.output = input;
UI.notify('Offset Unavailable', 'offset-notification');
callback();
}
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
return options.func(
r2, g2, b2, a2,
p.get(x, y, 0),
p.get(x, y, 1),
p.get(x, y, 2),
p.get(x, y, 3)
)
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
// run PixelManipulatin on second image's pixels
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
});
}
getPixels(priorStep.output.src, function(err, pixels) {
options.firstImagePixels = pixels;
function changePixel(r2, g2, b2, a2, x, y) {
// blend!
let p = options.firstImagePixels;
return options.func(
r2, g2, b2, a2,
p.get(x, y, 0),
p.get(x, y, 1),
p.get(x, y, 2),
p.get(x, y, 3)
);
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
// run PixelManipulatin on second image's pixels
return require('../_nomodule/PixelManipulation.js')(input, {
return {
options: options,
draw: draw,
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
UI: UI
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "blend",
"name": "Blend",
"description": "Blend two chosen image steps with the given function. Defaults to using the red channel from image 1 and the green and blue and alpha channels of image 2. Easier to use interfaces coming soon!",
"inputs": {
"offset": {

View File

@@ -1,81 +0,0 @@
module.exports = function(pixels, options, priorStep){
var $ = require('jquery'); // to make Blob-analysis work for node.js
var img = $(priorStep.imgElement);
if(Object.keys(img).length === 0){
img = $(priorStep.options.step.imgElement);
}
var canvas = document.createElement('canvas');
canvas.width = pixels.shape[0];
canvas.height = pixels.shape[1];
var ctx = canvas.getContext('2d');
ctx.drawImage(img[0], 0, 0);
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let src = cv.matFromImageData(imgData);
let dst = new cv.Mat();
let gray = new cv.Mat();
let opening = new cv.Mat();
let imageBg = new cv.Mat();
let imageFg = new cv.Mat();
let distTrans = new cv.Mat();
let unknown = new cv.Mat();
let markers = new cv.Mat();
// gray and threshold image
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
cv.threshold(gray, gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU);
// get background
let M = cv.Mat.ones(3, 3, cv.CV_8U);
cv.erode(gray, gray, M);
cv.dilate(gray, opening, M);
cv.dilate(opening, imageBg, M, new cv.Point(-1, -1), 3);
// distance transform
cv.distanceTransform(opening, distTrans, cv.DIST_L2, 5);
cv.normalize(distTrans, distTrans, 1, 0, cv.NORM_INF);
// get foreground
cv.threshold(distTrans, imageFg, 0.7 * 1, 255, cv.THRESH_BINARY);
imageFg.convertTo(imageFg, cv.CV_8U, 1, 0);
cv.subtract(imageBg, imageFg, unknown);
// get connected components markers
cv.connectedComponents(imageFg, markers);
for (let i = 0; i < markers.rows; i++) {
for (let j = 0; j < markers.cols; j++) {
markers.intPtr(i, j)[0] = markers.ucharPtr(i, j)[0] + 1;
if (unknown.ucharPtr(i, j)[0] == 255) {
markers.intPtr(i, j)[0] = 0;
}
}
}
cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
cv.watershed(src, markers);
// draw barriers
for (let i = 0; i < markers.rows; i++) {
for (let j = 0; j < markers.cols; j++) {
if (markers.intPtr(i, j)[0] == -1) {
src.ucharPtr(i, j)[0] = 255; // R
src.ucharPtr(i, j)[1] = 0; // G
src.ucharPtr(i, j)[2] = 0; // B
}
}
}
cv.imshow(canvas, src);
src.delete(); dst.delete(); gray.delete(); opening.delete(); imageBg.delete();
imageFg.delete(); distTrans.delete(); unknown.delete(); markers.delete(); M.delete();
var myImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pixels.data = myImageData.data;
return pixels;
};

View File

@@ -1,43 +0,0 @@
module.exports = function BlobAnalysis(options, UI){
var output;
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var priorStep = this.getStep(-1); // get the previous step to process it
function extraManipulation(pixels){
pixels = require('./BlobAnalysis')(pixels, options, priorStep);
return pixels;
}
function output(image, datauri, mimetype){
step.output = { src: datauri, format: mimetype};
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

@@ -1,4 +0,0 @@
module.exports = [
require('./Module'),
require('./info.json')
];

View File

@@ -1,6 +0,0 @@
{
"name": "Blob Analysis",
"description": "Blob/Region identification for microscopic images.",
"inputs": {},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blob-analysis"
}

View File

@@ -1,65 +1,84 @@
module.exports = exports = function(pixels, blur) {
const pixelSetter = require('../../util/pixelSetter.js');
let kernel = kernelGenerator(blur, 1), oldpix = require('lodash').cloneDeep(pixels);
kernel = flipKernel(kernel);
let kernel = kernelGenerator(blur),
pixs = {
r: [],
g: [],
b: [],
};
for (let y = 0; y < pixels.shape[1]; y++){
pixs.r.push([]);
pixs.g.push([]);
pixs.b.push([]);
for (let x = 0; x < pixels.shape[0]; x++){
pixs.r[y].push(pixels.get(x, y, 0));
pixs.g[y].push(pixels.get(x, y, 1));
pixs.b[y].push(pixels.get(x, y, 2));
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
acc[1] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 1) * kernel[a][b]);
acc[2] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 2) * kernel[a][b]);
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
}
}
return pixels;
const convolve = require('../_nomodule/gpuUtils').convolve;
const conPix = convolve([pixs.r, pixs.g, pixs.b], kernel);
for (let y = 0; y < pixels.shape[1]; y++){
for (let x = 0; x < pixels.shape[0]; x++){
var pixelvalue = [Math.max(0, Math.min(conPix[0][y][x], 255)),
Math.max(0, Math.min(conPix[1][y][x], 255)),
Math.max(0, Math.min(conPix[2][y][x], 255))];
pixelSetter(x, y, pixelvalue, pixels);
//Generates a 3x3 Gaussian kernel
function kernelGenerator(sigma, size) {
/*
Trying out a variable radius kernel not working as of now
*/
// const coeff = (1.0/(2.0*Math.PI*sigma*sigma))
// const expCoeff = -1 * (1.0/2.0 * sigma * sigma)
// let e = Math.E
// let result = []
// for(let i = -1 * size;i<=size;i++){
// let arr = []
// for(let j= -1 * size;j<=size;j++){
// arr.push(coeff * Math.pow(e,expCoeff * ((i * i) + (j*j))))
// }
// result.push(arr)
// }
// let sum = result.reduce((sum,val)=>{
// return val.reduce((sumInner,valInner)=>{
// return sumInner+valInner
// })
// })
// result = result.map(arr=>arr.map(val=>(val + 0.0)/(sum + 0.0)))
// return result
return [
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[5.0 / 159.0, 12.0 / 159.0, 15.0 / 159.0, 12.0 / 159.0, 5.0 / 159.0],
[4.0 / 159.0, 9.0 / 159.0, 12.0 / 159.0, 9.0 / 159.0, 4.0 / 159.0],
[2.0 / 159.0, 4.0 / 159.0, 5.0 / 159.0, 4.0 / 159.0, 2.0 / 159.0]
];
}
}
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1], result = [];
return pixels;
for (let i = -2; i <= 2; i++) {
let arr = [];
for (let j = -2; j <= 2; j++)
arr.push([x + i, y + j]);
//Generates a 5x5 Gaussian kernel
function kernelGenerator(sigma = 1) {
let kernel = [],
sum = 0;
if (sigma == 0) sigma += 0.05;
const s = 2 * Math.pow(sigma, 2);
for (let y = -2; y <= 2; y++) {
kernel.push([]);
for (let x = -2; x <= 2; x++) {
let r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
kernel[y + 2].push(Math.exp(-(r / s)));
sum += kernel[y + 2][x + 2];
}
result.push(arr);
}
return result;
}
for (let x = 0; x < 5; x++){
for (let y = 0; y < 5; y++){
kernel[y][x] = (kernel[y][x] / sum);
}
function flipKernel(kernel) {
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j]);
}
result.push(arr);
}
return result;
}
return kernel;
}
};
}

View File

@@ -3,45 +3,42 @@
*/
module.exports = function Blur(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.blur = options.blur || defaults.blur;
options.blur = parseFloat(options.blur);
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.blur = options.blur || defaults.blur;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Blur')(pixels, options.blur);
return pixels;
}
function extraManipulation(pixels) {
pixels = require('./Blur')(pixels, options.blur);
return pixels;
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "blur",
"name": "Blur",
"description": "Applies a Gaussian blur given by the intensity value",
"inputs": {
"blur": {
@@ -8,7 +8,7 @@
"default": 2,
"min": 0,
"max": 5,
"step": 0.05
"step": 0.25
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#blur-module"

View File

@@ -3,57 +3,55 @@
*/
module.exports = function Brightness(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
options.brightness = options.brightness || defaults.brightness;
options.brightness = options.brightness || defaults.brightness;
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
/*
/*
In this case progress is handled by changepixel internally otherwise progressObj
needs to be overriden and used
For eg. progressObj = new SomeProgressModule()
*/
var step = this, val = (options.brightness) / 100.0;
var step = this, val = (options.brightness) / 100.0;;
function changePixel(r, g, b, a) {
function changePixel(r, g, b, a) {
r = Math.min(val * r, 255);
g = Math.min(val * g, 255);
b = Math.min(val * b, 255);
return [r, g, b, a];
}
r = Math.min(val * r, 255);
g = Math.min(val * g, 255);
b = Math.min(val * b, 255);
return [r, g, b, a];
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui, //don't pass this in if you don't want your module to support progress bars
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "brightness",
"name": "Brightness",
"description": "Change the brightness of the image by given percent value",
"inputs": {
"brightness": {

View File

@@ -1,63 +0,0 @@
/*
* Changes the Canvas Size
*/
module.exports = function canvasResize(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
const pixelSetter = require('../../util/pixelSetter.js');
var output;
function draw(input, callback, progressObj) {
options.width = parseInt(options.width || defaults.width);
options.height = parseInt(options.height || defaults.height);
options.x = parseInt(options.x || defaults.x);
options.y = parseInt(options.y || defaults.y);
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function extraManipulation(pixels) {
let newPixels = require('ndarray')(new Uint8Array(4 * options.width * options.height).fill(0), [options.width, options.height, 4]);
let iMax = options.width - options.x,
jMax = options.height - options.y;
for (let i = 0; i < iMax && i < pixels.shape[0]; i++) {
for (let j = 0; j < jMax && j < pixels.shape[1]; j++) {
let x = i + options.x, y = j + options.y;
pixelSetter(x, y, [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2), pixels.get(i, j, 3)], newPixels);
}
}
return newPixels;
}
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};

View File

@@ -1,4 +0,0 @@
module.exports = [
require('./Module'),
require('./info.json')
];

View File

@@ -1,26 +0,0 @@
{
"name": "canvas-resize",
"description": "This module resizes the canvas and overlays the ouput of the previous step at given location",
"inputs": {
"width": {
"type": "integer",
"desc": "Final width of the canvas",
"default": 1000
},
"height": {
"type": "integer",
"desc": "Final height of the canvas",
"default": 1000
},
"x": {
"type": "integer",
"desc": "X-cord of the top left corner of the image on the canvas",
"default": 500
},
"y": {
"type": "float",
"desc": "Y-cord of the top left corner of the image on the canvas",
"default": 500
}
}
}

View File

@@ -17,9 +17,9 @@ module.exports = function Channel(options, UI) {
var step = this;
function changePixel(r, g, b, a) {
if (options.channel === 'red') return [r, 0, 0, a];
if (options.channel === 'green') return [0, g, 0, a];
if (options.channel === 'blue') return [0, 0, b, a];
if (options.channel === "red") return [r, 0, 0, a];
if (options.channel === "green") return [0, g, 0, a];
if (options.channel === "blue") return [0, 0, b, a];
}
function output(image, datauri, mimetype) {
@@ -31,13 +31,11 @@ module.exports = function Channel(options, UI) {
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
callback: callback
});
}
@@ -48,5 +46,5 @@ module.exports = function Channel(options, UI) {
draw: draw,
output: output,
UI: UI
};
};
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "channel",
"name": "Channel",
"description": "Displays only one color channel of an image -- default is green",
"inputs": {
"channel": {

View File

@@ -1,80 +1,81 @@
module.exports = function ColorTemperature(options, UI) {
const pixelSetter = require('../../util/pixelSetter.js');
var output;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
options.temperature = (options.temperature > '40000') ? '40000' : options.temperature;
options.temperature = (options.temperature > "40000") ? "40000" : options.temperature
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
function extraManipulation(pixels) {
let temp = parseInt(options.temperature);
temp /= 100;
let temp = parseInt(options.temperature)
temp /= 100
let r, g, b;
let r, g, b;
if (temp <= 66) {
r = 255;
g = Math.min(Math.max(99.4708025861 * Math.log(temp) - 161.1195681661, 0), 255);
} else {
r = Math.min(Math.max(329.698727446 * Math.pow(temp - 60, -0.1332047592), 0), 255);
g = Math.min(Math.max(288.1221695283 * Math.pow(temp - 60, -0.0755148492), 0), 255);
}
if (temp <= 66) {
r = 255;
g = Math.min(Math.max(99.4708025861 * Math.log(temp) - 161.1195681661, 0), 255);
} else {
r = Math.min(Math.max(329.698727446 * Math.pow(temp - 60, -0.1332047592), 0), 255);
g = Math.min(Math.max(288.1221695283 * Math.pow(temp - 60, -0.0755148492), 0), 255);
}
if (temp >= 66) {
b = 255;
} else if (temp <= 19) {
b = 0;
} else {
b = temp - 10;
b = Math.min(Math.max(138.5177312231 * Math.log(b) - 305.0447927307, 0), 255);
}
if (temp >= 66) {
b = 255;
} else if (temp <= 19) {
b = 0;
} else {
b = temp - 10;
b = Math.min(Math.max(138.5177312231 * Math.log(b) - 305.0447927307, 0), 255);
}
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
var rgbdata = [pixels.get(i, j, 0), pixels.get(i, j, 1), pixels.get(i, j, 2)];
rgbdata[0] = (255 / r) * rgbdata[0];
rgbdata[1] = (255 / g) * rgbdata[1];
rgbdata[2] = (255 / b) * rgbdata[2];
pixelSetter(i, j, rgbdata, pixels);
r_data = pixels.get(i, j, 0)
r_new_data = (255 / r) * r_data
pixels.set(i, j, 0, r_new_data)
g_data = pixels.get(i, j, 1)
g_new_data = (255 / g) * g_data
pixels.set(i, j, 1, g_new_data)
b_data = pixels.get(i, j, 2)
b_new_data = (255 / b) * b_data
pixels.set(i, j, 2, b_new_data)
}
}
return pixels
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
}
}
return pixels;
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback
});
}
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
return {
options: options,
draw: draw,
output: output,
UI: UI
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "color-temperature",
"name": "Color Temperature",
"description": "Changes the color temperature of the image.",
"inputs": {
"temperature": {
@@ -9,4 +9,4 @@
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#color-temperature"
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "colorbar",
"name": "Colorbar",
"description": "Generates a colorbar to lay over the image",
"inputs": {
"colormap": {

View File

@@ -1,27 +1,27 @@
/*
* Accepts a value from 0-255 and returns the new color-mapped pixel
* from a lookup table, which can be specified as an array of [begin, end]
* gradients, where begin and end are represented as [r, g, b] colors. In
* Accepts a value from 0-255 and returns the new color-mapped pixel
* from a lookup table, which can be specified as an array of [begin, end]
* gradients, where begin and end are represented as [r, g, b] colors. In
* combination, a lookup table which maps values from 0 - 255 smoothly from black to white looks like:
* [
* [0, [0, 0, 0], [255, 255, 255]],
* [1, [255, 255, 255], [255, 255, 255]]
* ]
*
*
* Adapted from bgamari's work in Infragram: https://github.com/p-v-o-s/infragram-js/commit/346c97576a07b71a55671d17e0153b7df74e803b
*/
module.exports = function Colormap(value, options) {
options.colormap = options.colormap || colormaps.default;
// if a lookup table is provided as an array:
if(typeof(options.colormap) == 'object')
if(typeof(options.colormap) == "object")
colormapFunction = colormap(options.colormap);
// if a stored colormap is named with a string like "fastie":
else if(colormaps.hasOwnProperty(options.colormap))
colormapFunction = colormaps[options.colormap];
else colormapFunction = colormaps.default;
return colormapFunction(value / 255.00);
};
}
function colormap(segments) {
return function(x) {
@@ -49,149 +49,149 @@ function colormap(segments) {
}
return result;
};
}
};
var colormaps = {
greyscale: colormap([
[0, [0, 0, 0], [255, 255, 255] ],
[1, [255, 255, 255], [255, 255, 255] ]
]),
[0, [0, 0, 0], [255, 255, 255] ],
[1, [255, 255, 255], [255, 255, 255] ]
]),
bluwhtgrngis: colormap([
[0, [6, 23, 86], [6, 25, 84] ],
[0.0625, [6, 25, 84], [6, 25, 84] ], //1
[0.125, [6, 25, 84], [6, 25, 84] ], //2
[0.1875, [6, 25, 84], [6, 25, 84] ],
[0.25, [6, 25, 84], [6, 25, 84] ],
[0.3125, [6, 25, 84], [9, 24, 84] ], //5
[0.3438, [9, 24, 84], [119, 120, 162] ], //5
[0.375, [119, 129, 162], [249, 250, 251] ], //6
[0.406, [249, 250, 251], [255, 255, 255] ], //6.5
[0.4375, [255, 255, 255], [255, 255, 255] ], //7 white
[0.50, [255, 255, 255], [214, 205, 191] ], //8
[0.52, [214, 205, 191], [178, 175, 96] ], //8.2
[0.5625, [178, 175, 96], [151, 176, 53] ], //9
[0.593, [151, 176, 53], [146, 188, 12] ], //9.5
[0.625, [146, 188, 12], [96, 161, 1] ], //10
[0.6875, [96, 161, 1], [30, 127, 3] ], //11
[0.75, [30, 127, 3], [0, 99, 1] ], //12
[0.8125, [0, 99, 1], [0, 74, 1] ], //13
[0.875, [0, 74, 1], [0, 52, 0] ], //14
[0.9375, [0, 52, 0], [0, 34, 0] ], //15
[0.968, [0, 34, 0], [68, 70, 67] ] //16
]),
bluwhtgrngis: colormap([
[0, [6,23,86], [6,25, 84] ],
[0.0625, [6,25,84], [6,25, 84] ],//1
[0.125, [6,25,84], [6,25, 84] ],//2
[0.1875, [6,25,84], [6,25, 84] ],
[0.25, [6,25,84], [6,25,84] ],
[0.3125, [6,25,84], [9,24, 84] ],//5
[0.3438, [9,24, 84], [119,120,162] ],//5
[0.375, [119,129,162],[249,250,251] ], //6
[0.406, [249,250,251],[255,255,255] ], //6.5
[0.4375, [255,255,255],[255,255,255] ], //7 white
[0.50, [255,255,255],[214,205,191] ],//8
[0.52, [214,205,191],[178,175,96] ],//8.2
[0.5625, [178,175,96], [151,176,53] ],//9
[0.593, [151,176,53], [146,188,12] ],//9.5
[0.625, [146,188,12], [96,161,1] ], //10
[0.6875, [96,161,1], [30,127,3] ],//11
[0.75, [30,127,3], [0,99,1] ],//12
[0.8125, [0,99,1], [0,74,1] ],//13
[0.875, [0,74,1], [0,52, 0] ],//14
[0.9375, [0,52, 0], [0,34,0] ], //15
[0.968, [0,34,0], [68,70,67] ] //16
]),
brntogrn: colormap([
[0, [110, 12, 3], [118, 6, 1] ],
[0.0625, [118, 6, 1], [141, 19, 6] ],
[0.125, [141, 19, 6], [165, 35, 13] ],
[0.1875, [165, 35, 13], [177, 59, 25] ],
[0.2188, [177, 59, 25], [192, 91, 36] ],
[0.25, [192, 91, 36], [214, 145, 76] ],
[0.3125, [214, 145, 76], [230, 183, 134] ],
[0.375, [230, 183, 134], [243, 224, 194]],
[0.4375, [243, 224, 194], [250, 252, 229] ],
[0.50, [250, 252, 229], [217, 235, 185] ],
[0.5625, [217, 235, 185], [184, 218, 143] ],
[0.625, [184, 218, 143], [141, 202, 89] ],
[0.6875, [141, 202, 89], [80, 176, 61] ],
[0.75, [80, 176, 61], [0, 147, 32] ],
[0.8125, [0, 147, 32], [1, 122, 22] ],
[0.875, [1, 122, 22], [0, 114, 19] ],
[0.90, [0, 114, 19], [0, 105, 18] ],
[0.9375, [0, 105, 18], [7, 70, 14] ]
[0, [110,12,3], [118,6,1] ],
[0.0625, [118,6,1], [141,19,6] ],
[0.125, [141,19,6], [165,35,13] ],
[0.1875, [165,35,13], [177,59,25] ],
[0.2188, [177,59,25], [192,91,36] ],
[0.25, [192,91,36], [214, 145, 76] ],
[0.3125, [214,145,76], [230,183,134] ],
[0.375, [230,183,134],[243, 224, 194]],
[0.4375, [243,224,194],[250,252,229] ],
[0.50, [250,252,229],[217,235,185] ],
[0.5625, [217,235,185],[184,218,143] ],
[0.625, [184,218,143],[141,202,89] ],
[0.6875, [141,202,89], [80,176,61] ],
[0.75, [80,176,61], [0, 147, 32] ],
[0.8125, [0,147,32], [1, 122, 22] ],
[0.875, [1,122,22], [0, 114, 19] ],
[0.90, [0,114,19], [0,105,18] ],
[0.9375, [0,105,18], [7,70,14] ]
]),
]),
blutoredjet: colormap([
[0, [0, 0, 140], [1, 1, 186] ],
[0.0625, [1, 1, 186], [0, 1, 248] ],
[0.125, [0, 1, 248], [0, 70, 254] ],
[0.1875, [0, 70, 254], [0, 130, 255] ],
[0.25, [0, 130, 255], [2, 160, 255] ],
[0.2813, [2, 160, 255], [0, 187, 255] ], //inset
[0.3125, [0, 187, 255], [6, 250, 255] ],
// [0.348, [0,218,255], [8,252,251] ],//inset
[0.375, [8, 252, 251], [27, 254, 228] ],
[0.406, [27, 254, 228], [70, 255, 187] ], //insert
[0.4375, [70, 255, 187], [104, 254, 151]],
[0.47, [104, 254, 151], [132, 255, 19] ], //insert
[0.50, [132, 255, 19], [195, 255, 60] ],
[0.5625, [195, 255, 60], [231, 254, 25] ],
[0.5976, [231, 254, 25], [253, 246, 1] ], //insert
[0.625, [253, 246, 1], [252, 210, 1] ], //yellow
[0.657, [252, 210, 1], [255, 183, 0] ], //insert
[0.6875, [255, 183, 0], [255, 125, 2] ],
[0.75, [255, 125, 2], [255, 65, 1] ],
[0.8125, [255, 65, 1], [247, 1, 1] ],
[0.875, [247, 1, 1], [200, 1, 3] ],
[0.9375, [200, 1, 3], [122, 3, 2] ]
[0, [0,0,140], [1,1,186] ],
[0.0625, [1,1,186], [0,1,248] ],
[0.125, [0,1,248], [0,70,254] ],
[0.1875, [0,70,254], [0,130,255] ],
[0.25, [0,130,255], [2,160,255] ],
[0.2813, [2,160,255], [0,187,255] ], //inset
[0.3125, [0,187,255], [6,250,255] ],
// [0.348, [0,218,255], [8,252,251] ],//inset
[0.375, [8,252,251], [27,254,228] ],
[0.406, [27,254,228], [70,255,187] ], //insert
[0.4375, [70,255,187], [104,254,151]],
[0.47, [104,254,151],[132,255,19] ],//insert
[0.50, [132,255,19], [195,255,60] ],
[0.5625, [195,255,60], [231,254,25] ],
[0.5976, [231,254,25], [253,246,1] ],//insert
[0.625, [253,246,1], [252,210,1] ], //yellow
[0.657, [252,210,1], [255,183,0] ],//insert
[0.6875, [255,183,0], [255,125,2] ],
[0.75, [255,125,2], [255,65, 1] ],
[0.8125, [255,65, 1], [247, 1, 1] ],
[0.875, [247,1,1], [200, 1, 3] ],
[0.9375, [200,1,3], [122, 3, 2] ]
]),
]),
colors16: colormap([
[0, [0, 0, 0], [0, 0, 0] ],
[0.0625, [3, 1, 172], [3, 1, 172] ],
[0.125, [3, 1, 222], [3, 1, 222] ],
[0.1875, [0, 111, 255], [0, 111, 255] ],
[0.25, [3, 172, 255], [3, 172, 255] ],
[0.3125, [1, 226, 255], [1, 226, 255] ],
[0.375, [2, 255, 0], [2, 255, 0] ],
[0.4375, [198, 254, 0], [190, 254, 0] ],
[0.50, [252, 255, 0], [252, 255, 0] ],
[0.5625, [255, 223, 3], [255, 223, 3] ],
[0.625, [255, 143, 3], [255, 143, 3] ],
[0.6875, [255, 95, 3], [255, 95, 3] ],
[0.75, [242, 0, 1], [242, 0, 1] ],
[0.8125, [245, 0, 170], [245, 0, 170] ],
[0.875, [223, 180, 225], [223, 180, 225] ],
[0.9375, [255, 255, 255], [255, 255, 255]]
[0, [0,0,0], [0,0,0] ],
[0.0625, [3,1,172], [3,1,172] ],
[0.125, [3,1,222], [3,1, 222] ],
[0.1875, [0,111,255], [0,111,255] ],
[0.25, [3,172,255], [3,172,255] ],
[0.3125, [1,226,255], [1,226,255] ],
[0.375, [2,255,0], [2,255,0] ],
[0.4375, [198,254,0], [190,254,0] ],
[0.50, [252,255,0], [252,255,0] ],
[0.5625, [255,223,3], [255,223,3] ],
[0.625, [255,143,3], [255,143,3] ],
[0.6875, [255,95,3], [255,95,3] ],
[0.75, [242,0,1], [242,0,1] ],
[0.8125, [245,0,170], [245,0,170] ],
[0.875, [223,180,225], [223,180,225] ],
[0.9375, [255,255,255], [255,255, 255]]
]),
]),
default: colormap([
[0, [45, 1, 121], [25, 1, 137] ],
[0.125, [25, 1, 137], [0, 6, 156] ],
[0.1875, [0, 6, 156], [7, 41, 172] ],
[0.25, [7, 41, 172], [22, 84, 187] ],
[0.3125, [22, 84, 187], [25, 125, 194] ],
[0.375, [25, 125, 194], [26, 177, 197] ],
[0.4375, [26, 177, 197], [23, 199, 193] ],
[0.47, [23, 199, 193], [25, 200, 170] ],
[0.50, [25, 200, 170], [21, 209, 27] ],
[0.5625, [21, 209, 27], [108, 215, 18] ],
[0.625, [108, 215, 18], [166, 218, 19] ],
[0.6875, [166, 218, 19], [206, 221, 20] ],
[0.75, [206, 221, 20], [222, 213, 19 ] ],
[0.7813, [222, 213, 19], [222, 191, 19]],
[0.8125, [222, 191, 19], [227, 133, 17] ],
[0.875, [227, 133, 17], [231, 83, 16] ],
[0.9375, [231, 83, 16], [220, 61, 48] ]
default: colormap([
[0, [45,1,121], [25,1,137] ],
[0.125, [25,1,137], [0,6,156] ],
[0.1875, [0,6,156], [7,41,172] ],
[0.25, [7,41,172], [22,84,187] ],
[0.3125, [22,84,187], [25,125,194] ],
[0.375, [25,125,194], [26,177,197] ],
[0.4375, [26,177,197], [23,199,193] ],
[0.47, [23,199,193], [25, 200,170] ],
[0.50, [25, 200,170], [21,209,27] ],
[0.5625, [21,209,27], [108,215,18] ],
[0.625, [108,215,18], [166,218,19] ],
[0.6875, [166,218,19], [206,221,20] ],
[0.75, [206,221,20], [222,213,19 ] ],
[0.7813, [222,213,19], [222, 191, 19]],
[0.8125, [222, 191, 19], [227,133,17] ],
[0.875, [227,133,17], [231,83,16] ],
[0.9375, [231,83,16], [220,61,48] ]
]),
]),
fastie: colormap([
[0, [255, 255, 255], [0, 0, 0] ],
[0.167, [0, 0, 0], [255, 255, 255] ],
[0.33, [255, 255, 255], [0, 0, 0] ],
[0.5, [0, 0, 0], [140, 140, 255] ],
[0.55, [140, 140, 255], [0, 255, 0] ],
[0.63, [0, 255, 0], [255, 255, 0] ],
[0.75, [255, 255, 0], [255, 0, 0] ],
[0.95, [255, 0, 0], [255, 0, 255] ]
]),
[0, [255, 255, 255], [0, 0, 0] ],
[0.167, [0, 0, 0], [255, 255, 255] ],
[0.33, [255, 255, 255], [0, 0, 0] ],
[0.5, [0, 0, 0], [140, 140, 255] ],
[0.55, [140, 140, 255], [0, 255, 0] ],
[0.63, [0, 255, 0], [255, 255, 0] ],
[0.75, [255, 255, 0], [255, 0, 0] ],
[0.95, [255, 0, 0], [255, 0, 255] ]
]),
stretched: colormap([
[0, [0, 0, 255], [0, 0, 255] ],
[0.1, [0, 0, 255], [38, 195, 195] ],
[0.5, [0, 150, 0], [255, 255, 0] ],
[0.7, [255, 255, 0], [255, 50, 50] ],
[0.9, [255, 50, 50], [255, 50, 50] ]
])
[0, [0, 0, 255], [0, 0, 255] ],
[0.1, [0, 0, 255], [38, 195, 195] ],
[0.5, [0, 150, 0], [255, 255, 0] ],
[0.7, [255, 255, 0], [255, 50, 50] ],
[0.9, [255, 50, 50], [255, 50, 50] ]
])
};
}

View File

@@ -24,13 +24,11 @@ module.exports = function Colormap(options, UI) {
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
changePixel: changePixel,
format: input.format,
image: options.image,
inBrowser: options.inBrowser,
callback: callback,
useWasm:options.useWasm
callback: callback
});
}
@@ -40,5 +38,5 @@ module.exports = function Colormap(options, UI) {
draw: draw,
output: output,
UI: UI
};
};
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "colormap",
"name": "Colormap",
"description": "Maps brightness values (average of red, green & blue) to a given color lookup table, made up of a set of one more color gradients.\n\nFor example, 'cooler' colors like blue could represent low values, while 'hot' colors like red could represent high values.",
"inputs": {
"colormap": {

View File

@@ -1,30 +1,47 @@
var _ = require('lodash');
const pixelSetter = require('../../util/pixelSetter.js');
module.exports = exports = function(pixels, contrast) {
let oldpix = _.cloneDeep(pixels);
contrast = Number(contrast);
if (contrast < -100) contrast = -100;
if (contrast > 100) contrast = 100;
contrast = (100.0 + contrast) / 100.0;
contrast *= contrast;
let oldpix = _.cloneDeep(pixels);
contrast = Number(contrast)
if (contrast < -100) contrast = -100;
if (contrast > 100) contrast = 100;
contrast = (100.0 + contrast) / 100.0;
contrast *= contrast;
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
var rgbarray = [oldpix.get(i, j, 0) / 255.0, oldpix.get(i, j, 1) / 255.0, oldpix.get(i, j, 2) / 255.0];
for(var idx = 0;idx < 3;idx++){
rgbarray[idx] -= 0.5;
rgbarray[idx] *= contrast;
rgbarray[idx] += 0.5;
rgbarray[idx] *= 255;
if (rgbarray[idx] < 0) rgbarray[idx] = 0;
if (rgbarray[idx] > 255) rgbarray[idx] = 255;
}
pixelSetter(i, j, rgbarray, pixels);
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
var r = oldpix.get(i, j, 0) / 255.0;
r -= 0.5;
r *= contrast;
r += 0.5;
r *= 255;
if (r < 0) r = 0;
if (r > 255) r = 255;
var g = oldpix.get(i, j, 1) / 255.0;
g -= 0.5;
g *= contrast;
g += 0.5;
g *= 255;
if (g < 0) g = 0;
if (g > 255) g = 255;
var b = oldpix.get(i, j, 2) / 255.0;
b -= 0.5;
b *= contrast;
b += 0.5;
b *= 255;
if (b < 0) b = 0;
if (b > 255) b = 255;
pixels.set(i, j, 0, r);
pixels.set(i, j, 1, g);
pixels.set(i, j, 2, b);
}
}
}
return pixels;
};
return pixels;
}

View File

@@ -4,44 +4,42 @@
module.exports = function Contrast(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.contrast = options.contrast || defaults.contrast;
var output;
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.contrast = options.contrast || defaults.contrast;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Contrast')(pixels, options.contrast);
return pixels;
}
function extraManipulation(pixels) {
pixels = require('./Contrast')(pixels, options.contrast)
return pixels
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
// This output is accessible by Image Sequencer
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,5 +1,5 @@
{
"name": "contrast",
"name": "Contrast",
"description": "Change the contrast of the image by given value",
"inputs": {
"contrast": {

View File

@@ -1,51 +1,71 @@
var _ = require('lodash');
const pixelSetter = require('../../util/pixelSetter.js');
module.exports = exports = function(pixels, constantFactor, kernelValues) {
let kernel = kernelGenerator(constantFactor, kernelValues), oldpix = _.cloneDeep(pixels);
kernel = flipKernel(kernel);
module.exports = exports = function(pixels, constantFactor, kernelValues, texMode) {
let kernel = kernelGenerator(constantFactor, kernelValues),
pixs = {
r: [],
g: [],
b: [],
};
for (let y = 0; y < pixels.shape[1]; y++){
pixs.r.push([]);
pixs.g.push([]);
pixs.b.push([]);
for (let x = 0; x < pixels.shape[0]; x++){
pixs.r[y].push(pixels.get(x, y, 0));
pixs.g[y].push(pixels.get(x, y, 1));
pixs.b[y].push(pixels.get(x, y, 2));
for (let i = 0; i < pixels.shape[0]; i++) {
for (let j = 0; j < pixels.shape[1]; j++) {
let neighboutPos = getNeighbouringPixelPositions([i, j]);
let acc = [0.0, 0.0, 0.0, 0.0];
for (let a = 0; a < kernel.length; a++) {
for (let b = 0; b < kernel.length; b++) {
acc[0] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 0) * kernel[a][b]);
acc[1] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 1) * kernel[a][b]);
acc[2] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 2) * kernel[a][b]);
acc[3] += (oldpix.get(neighboutPos[a][b][0], neighboutPos[a][b][1], 3) * kernel[a][b]);
}
}
acc[0] = Math.min(acc[0], 255);
acc[1] = Math.min(acc[1], 255);
acc[2] = Math.min(acc[2], 255);
pixels.set(i, j, 0, acc[0]);
pixels.set(i, j, 1, acc[1]);
pixels.set(i, j, 2, acc[2]);
}
}
}
return pixels;
const convolve = require('../_nomodule/gpuUtils').convolve;
const conPix = convolve([pixs.r, pixs.g, pixs.b], kernel, (pixels.shape[0] * pixels.shape[1]) < 400000 ? true : false);
for (let y = 0; y < pixels.shape[1]; y++){
for (let x = 0; x < pixels.shape[0]; x++){
var value = [Math.max(0, Math.min(conPix[0][y][x], 255)), Math.max(0, Math.min(conPix[1][y][x], 255)), Math.max(0, Math.min(conPix[2][y][x], 255))];
pixelSetter(x, y, value, pixels);
function kernelGenerator(constantFactor, kernelValues) {
kernelValues = kernelValues.split(" ");
for (i = 0; i < 9; i++) {
kernelValues[i] = Number(kernelValues[i]) * constantFactor;
}
let k = 0;
let arr = [];
for (i = 0; i < 3; i++) {
let columns = [];
for (j = 0; j < 3; j++) {
columns.push(kernelValues[k]);
k += 1;
}
arr.push(columns);
}
return arr;
}
}
return pixels;
};
function kernelGenerator(constantFactor, kernelValues) {
kernelValues = kernelValues.split(' ');
for (i = 0; i < 9; i++) {
kernelValues[i] = Number(kernelValues[i]) * constantFactor;
}
let k = 0;
let arr = [];
for (y = 0; y < 3; y++) {
arr.push([]);
for (x = 0; x < 3; x++) {
arr[y].push(kernelValues[k]);
k += 1;
function getNeighbouringPixelPositions(pixelPosition) {
let x = pixelPosition[0], y = pixelPosition[1], result = [];
for (let i = -1; i <= 1; i++) {
let arr = [];
for (let j = -1; j <= 1; j++)
arr.push([x + i, y + j]);
result.push(arr);
}
return result;
}
function flipKernel(kernel) {
let result = [];
for (let i = kernel.length - 1; i >= 0; i--) {
let arr = [];
for (let j = kernel[i].length - 1; j >= 0; j--) {
arr.push(kernel[i][j]);
}
result.push(arr);
}
return result;
}
}
return arr;
}

View File

@@ -1,45 +1,42 @@
module.exports = function Convolution(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
options.kernelValues = options.kernelValues || defaults.kernelValues;
options.constantFactor = options.constantFactor || defaults.constantFactor;
options.texMode = options.texMode || defaults.texMode;
var output;
options.kernelValues = options.kernelValues || defaults.kernelValues;
options.constantFactor = options.constantFactor || defaults.constantFactor;
var output;
function draw(input, callback, progressObj) {
function draw(input, callback, progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
var step = this;
function extraManipulation(pixels) {
pixels = require('./Convolution')(pixels, options.constantFactor, options.kernelValues, options.texMode);
return pixels;
}
function extraManipulation(pixels) {
pixels = require('./Convolution')(pixels, options.constantFactor, options.kernelValues);
return pixels;
}
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype) {
step.output = { src: datauri, format: mimetype };
step.output = { src: datauri, format: mimetype };
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback
});
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
extraManipulation: extraManipulation,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
});
}
return {
options: options,
draw: draw,
output: output,
UI: UI
};
};
return {
options: options,
draw: draw,
output: output,
UI: UI
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

View File

@@ -1,15 +1,14 @@
{
"name": "convolution",
"name": "Convolution",
"description": "Image Convolution using a given 3x3 kernel matrix <a href='https://en.wikipedia.org/wiki/Kernel_(image_processing)'>Read more</a>",
"inputs": {
"constantFactor":{
"type": "float",
"desc": "a constant factor, multiplies all the kernel values by that factor",
"default": 0.111,
"min": 0.001,
"max": 2,
"step": 0.001
"default": 0.1111,
"placeholder": 0.1111
},
"kernelValues": {
"type": "string",
"desc": "nine space separated numbers representing the kernel values in left to right and top to bottom format.",

View File

@@ -1,12 +1,12 @@
module.exports = function Crop(input, options, callback) {
module.exports = function Crop(input,options,callback) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
var getPixels = require('get-pixels'),
savePixels = require('save-pixels');
savePixels = require('save-pixels');
options.x = parseInt(options.x) || defaults.x;
options.y = parseInt(options.y) || defaults.y;
getPixels(input.src, function(err, pixels){
getPixels(input.src,function(err,pixels){
options.w = parseInt(options.w) || Math.floor(pixels.shape[0]);
options.h = parseInt(options.h) || Math.floor(pixels.shape[1]);
options.backgroundColor = options.backgroundColor || defaults.backgroundColor;
@@ -17,29 +17,21 @@ module.exports = function Crop(input, options, callback) {
var iw = pixels.shape[0]; //Width of Original Image
var ih = pixels.shape[1]; //Height of Original Image
var backgroundArray = [];
backgroundColor = options.backgroundColor.substring(options.backgroundColor.indexOf('(') + 1, options.backgroundColor.length - 1); // extract only the values from rgba(_,_,_,_)
backgroundColor = backgroundColor.split(',');
backgroundColor = options.backgroundColor.split(" ");
for(var i = 0; i < w ; i++){
backgroundArray = backgroundArray.concat([backgroundColor[0], backgroundColor[1], backgroundColor[2], backgroundColor[3]]);
backgroundArray = backgroundArray.concat([backgroundColor[0],backgroundColor[1],backgroundColor[2],backgroundColor[3]]);
}
// var newarray = new Uint8Array(4*w*h);
var array = [];
var newarray = new Uint8Array(4*w*h);
for (var n = oy; n < oy + h; n++) {
var offsetValue = 4 * w * n;
if(n < ih){
var start = n * 4 * iw + ox * 4;
var end = n * 4 * iw + ox * 4 + 4 * w;
var pushArray = Array.from(pixels.data.slice(start, end ));
array.push.apply(array, pushArray);
if(n<ih){
newarray.set(pixels.data.slice(n*4*iw + ox, n*4*iw + ox + 4*w),4*w*(n-oy));
} else {
array.push.apply(array, backgroundArray);
newarray.set(backgroundArray,4*w*(n-oy));
}
}
var newarray = Uint8Array.from(array);
pixels.data = newarray;
pixels.shape = [w, h, 4];
pixels.stride[1] = 4 * w;
pixels.shape = [w,h,4];
pixels.stride[1] = 4*w;
options.format = input.format;
@@ -55,7 +47,7 @@ module.exports = function Crop(input, options, callback) {
r.on('end', function(){
var data = Buffer.concat(chunks, totalLength).toString('base64');
var datauri = 'data:image/' + options.format + ';base64,' + data;
callback(datauri, options.format);
callback(datauri,options.format);
});
});
};

View File

@@ -22,7 +22,7 @@ module.exports = function CropModule(options, UI) {
setupComplete = false;
// This function is caled everytime the step has to be redrawn
function draw(input, callback) {
function draw(input,callback) {
var step = this;
@@ -32,7 +32,7 @@ module.exports = function CropModule(options, UI) {
var parseCornerCoordinateInputs = require('../../util/ParseInputCoordinates');
//parse the inputs
parseCornerCoordinateInputs(options, {
parseCornerCoordinateInputs(options,{
src: input.src,
x: { valInp: options.x, type: 'horizontal' },
y: { valInp: options.y, type: 'vertical' },
@@ -51,7 +51,7 @@ module.exports = function CropModule(options, UI) {
step.output = {
src: out,
format: format
};
}
// This output is accessible to the UI
options.step.output = out;
@@ -81,5 +81,5 @@ module.exports = function CropModule(options, UI) {
draw: draw,
output: output,
UI: UI
};
};
}
}

View File

@@ -2,7 +2,7 @@
module.exports = function CropModuleUi(step, ui) {
let inputWidth = 0,
inputHeight = 0;
inputHeight = 0;
// We don't have input image dimensions at the
// time of setting up the UI; that comes when draw() is triggered.
@@ -10,7 +10,7 @@ module.exports = function CropModuleUi(step, ui) {
// TODO: link this to an event rather than an explicit call in Module.js
function setup() {
let x = 0,
y = 0;
y = 0;
// display original uncropped input image on initial setup
showOriginal();
@@ -42,21 +42,20 @@ module.exports = function CropModuleUi(step, ui) {
converted[2],
converted[3]
);
$($(imgEl()).parents()[3]).find('input').trigger('change');
}
});
}
function convertToNatural(_x, _y, _width, _height) {
let displayWidth = $(imgEl()).width(),
displayHeight = $(imgEl()).height();
displayHeight = $(imgEl()).height();
// return in same order [ x, y, width, height ]:
return [
Math.floor(( _x / displayWidth ) * inputWidth),
Math.floor(( _y / displayHeight ) * inputHeight),
Math.floor(( _width / displayWidth ) * inputWidth),
Math.floor(( _height / displayHeight ) * inputHeight)
];
]
}
function remove() {
@@ -78,7 +77,7 @@ module.exports = function CropModuleUi(step, ui) {
}
function setOptions(x1, y1, width, height) {
let options = $($(imgEl()).parents()[3]).find('input');
let options = $($(imgEl()).parents()[2]).find("input");
options[0].value = x1;
options[1].value = y1;
options[2].value = width;
@@ -94,5 +93,5 @@ module.exports = function CropModuleUi(step, ui) {
setup: setup,
remove: remove,
hide: hide
};
};
}
}

View File

@@ -1,4 +1,4 @@
module.exports = [
require('./Module'),
require('./info.json')
];
require('./Module'),
require('./info.json')
]

Some files were not shown because too many files have changed in this diff Show More