Compare commits

..

1 Commits

Author SHA1 Message Date
Jeffrey Warren
ee4ba6fb41 Update diagram 2019-03-22 15:53:17 -04:00
276 changed files with 99010 additions and 11925 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!

6
.gitignore vendored
View File

@@ -27,10 +27,6 @@ build/Release
node_modules
node_modules/*
# Dist Files
dist/*
dist
# Optional npm cache directory
.npm
@@ -49,4 +45,4 @@ test/core/modules/test_outputs/*
node_modules/
node_modules/*
test_outputs
/test_outputs
/test_outputs

View File

@@ -37,8 +37,6 @@ test.js
output.txt
output/
examples/
icons/

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)
****
@@ -32,7 +27,7 @@ If you find a bug please list it here, and help us develop Image Sequencer by [o
## Contributing modules
Most contributions can happen in modules, rather than to core library code. Modules and their [corresponding info files](#info-file) are included into the library in this file: https://github.com/publiclab/image-sequencer/blob/main/src/Modules.js#L5-L7
Most contributions can happen in modules, rather than to core library code. Modules and their [corresponding info files](#info-file) are included into the library in this file: https://github.com/publiclab/image-sequencer/blob/master/src/Modules.js#L5-L7
Module names, descriptions, and parameters are set in the `info.json` file -- [see below](#info-file).
@@ -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
@@ -160,7 +142,7 @@ input = {
pixelManipulation: "general purpose pixel manipulation API, see https://github.com/publiclab/image-sequencer/blob/master/src/modules/_nomodule/PixelManipulation.js"
}
```
For example usage of pixelManipulation see https://github.com/publiclab/image-sequencer/blob/main/src/modules/Invert/Module.js
For example usage for pixelManipulation see https://github.com/publiclab/image-sequencer/blob/master/src/modules/Invert/Module.js
**The module is included in the browser inside a script tag and since the code runs directly in the browser if any other module is required apart from the apis available on the input object, it should be either bundled with the module code and imported in es6 format or the module code must be browserified before distribution for browser**
@@ -280,12 +262,11 @@ 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
See existing module `green-channel` for an example: https://github.com/publiclab/image-sequencer/tree/master/src/modules/GreenChannel/Module.js
The `channel` module is included into the core modules here: https://github.com/publiclab/image-sequencer/blob/main/src/Modules.js#L5-L7
The `green-channel` module is included into the core modules here: https://github.com/publiclab/image-sequencer/blob/master/src/Modules.js#L5-L7
For help integrating, please open an issue.
@@ -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,56 +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;
#### 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"]);
};

110
README.md
View File

@@ -2,11 +2,10 @@ 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
- **Stable Branch**: https://github.com/publiclab/image-sequencer/tree/stable/
**Latest Stable Demo**: https://sequencer.publiclab.org
**Latest Beta Demo**: https://beta.sequencer.publiclab.org
## Why
@@ -21,7 +20,7 @@ The following diagrams attempt to explain how the applications various component
![general diagram](https://publiclab.org/i/30547.png?s=o)
![workflow diagram](https://raw.githubusercontent.com/publiclab/image-sequencer/main/examples/images/diagram-workflows.png)
![workflow diagram](https://raw.githubusercontent.com/publiclab/image-sequencer/master/examples/images/diagram-workflows.png)
It also for prototypes other related ideas:
@@ -29,17 +28,15 @@ It also for prototypes other related ideas:
* test-based image processing -- the ability to create a sequence of steps that do the same task as other image processing tools, provable with example before/after images to compare with
* logging each step -- to produce an evidentiary record of modifications to an original image
* cascading changes -- change an earlier step's settings, and see those changes affect later steps
* "small modules" -- based extensibility: see [Contributing](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md)
* "small modules" -- based extensibility: see [Contributing](https://github.com/publiclab/image-sequencer/blob/master/CONTRIBUTING.md)
## Examples
* [Simple Demo](https://sequencer.publiclab.org)
* [Latest Beta Demo](https://beta.sequencer.publiclab.org)
* [Simple Demo](https://publiclab.github.io/image-sequencer/)
A diagram of this running 5 steps on a single sample image may help explain how it works:
![example workflow](https://raw.githubusercontent.com/publiclab/image-sequencer/main/examples/images/diagram-6-steps.png)
![example workflow](https://raw.githubusercontent.com/publiclab/image-sequencer/master/examples/images/diagram-6-steps.png)
## Jump to:
@@ -50,8 +47,8 @@ A diagram of this running 5 steps on a single sample image may help explain how
* [Method Chaining](#method-chaining)
* [Multiple Images](#multiple-images)
* [Creating a User Interface](#creating-a-user-interface)
* [Contributing](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md)
* [Submit a Module](https://github.com/publiclab/image-sequencer/blob/main/CONTRIBUTING.md#contributing-modules)
* [Contributing](https://github.com/publiclab/image-sequencer/blob/master/CONTRIBUTING.md)
* [Submit a Module](https://github.com/publiclab/image-sequencer/blob/master/CONTRIBUTING.md#contributing-modules)
* [Get Demo Bookmarklet](https://publiclab.org/w/imagesequencerbookmarklet)
## Installation
@@ -59,12 +56,12 @@ 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 `sudo npm run setup` followed by `npm start`
### Windows
Our npm scripts do not support windows shells, please run the following snippet in PowerShell.
```powershell
npm i ; npm i -g grunt grunt-cli ; grunt build; grunt serve
npm i ; npm i -g grunt grunt-cli ; grunt serve
```
In case of a port conflict please run the following
```powershell
@@ -73,12 +70,12 @@ npm i -g http-server ; http-server -p 3000
### Browser
Just include [image-sequencer.min.js](https://github.com/publiclab/image-sequencer/blob/stable/dist/image-sequencer.min.js) in the Head section of your web page. See the [demo here](https://sequencer.publiclab.org)!
Just include [image-sequencer.js](https://publiclab.github.io/image-sequencer/dist/image-sequencer.js) in the Head section of your web page. See the [demo here](https://publiclab.github.io/image-sequencer/)!
### Node (via NPM)
(You must have NPM for this)
Add `image-sequencer` to your list of dependencies and run `npm install`
Add `image-sequencer` to your list of dependencies and run `$ npm install`
### CLI
@@ -95,7 +92,7 @@ $ npm install image-sequencer -g
```
$ npm run debug invert
```
## Quick Usage
### Initializing the Sequencer
@@ -115,7 +112,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 +120,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 +147,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 +155,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 +198,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 +216,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 +238,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 +395,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 +434,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 +511,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 +541,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
```

18088
dist/image-sequencer-ui.js vendored Normal file

File diff suppressed because it is too large Load Diff

1
dist/image-sequencer-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

73628
dist/image-sequencer.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/image-sequencer.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/manipulation.wasm vendored

Binary file not shown.

View File

@@ -37,8 +37,7 @@ List of Module Documentations
32. [Saturation](#saturation-module)
33. [Threshold](#threshold)
34. [Tint](#tint)
35. [ColorTemperature](#color-temperature)
36. [Grid-Overlay](#grid-overlay)
35. [WhiteBalance](#white-balance)
## crop-module
@@ -572,32 +571,17 @@ where `options` is an object with the following property:
* factor : amount of tint (default 0.5)
## Color Temperature
## White Balance
This changes the color temperature of the image.
This Change the colour balance of the image by adjusting the colour temperature.
## Usage
```js
sequencer.loadImage('PATH')
.addSteps('color-temperature',options)
.addSteps('white-balance',options)
.run()
```
where `options` is an object with the following property:
* temperature : temperature between 0 - 40,000 kelvin (default 6000)
## 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.

View File

@@ -1,14 +1,14 @@
/* https://github.com/theleagueof/league-spartan */
@font-face {
font-family: 'League Spartan';
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot');
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot?#iefix') format('embedded-opentype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff2') format('woff2'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff') format('woff'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.ttf') format('truetype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.svg#league_spartanbold') format('svg');
font-weight: bold;
font-style: normal;
font-family: 'League Spartan';
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot');
src: url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.eot?#iefix') format('embedded-opentype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff2') format('woff2'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.woff') format('woff'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.ttf') format('truetype'),
url('https://raw.githubusercontent.com/theleagueof/league-spartan/master/_webfonts/leaguespartan-bold.svg#league_spartanbold') format('svg');
font-weight: bold;
font-style: normal;
}
body {
@@ -18,19 +18,11 @@ body {
background: #f8f8fa;
}
footer {
margin-top: 40px;
}
h1 {
font-family: 'League Spartan';
color: #445;
}
body > .container,
body > .container-fluid {
}
.center-align {
display: flex;
justify-content: center;
@@ -79,6 +71,17 @@ body > .container-fluid {
margin-bottom: 20px;
}
.details {
border-top: 3px solid #444;
padding-left: 6px;
}
.details h3 {
font-family: monospace;
margin-top: 12px;
font-size: 1.3em;
}
.det {
padding: 10px 16px;
text-decoration: italic;
@@ -97,6 +100,11 @@ body > .container-fluid {
color: #444;
}
.load-spin{
position: absolute;
right: 0px;
}
#addStep {
max-width: 500px;
margin: 20px auto;
@@ -151,19 +159,19 @@ body > .container-fluid {
}
#move-up {
position: fixed;
bottom: 50px;
right: 40px;
z-index: 550;
display: none;
background:transparent;
border:none;
position: fixed;
bottom: 50px;
right: 40px;
z-index: 550;
display: none;
background:transparent;
border:none;
}
#move-up i {
font-size:60px;
opacity:0.7;
color:#BABABA;
font-size:60px;
opacity:0.7;
color:#BABABA;
}
.btn-circle{
@@ -200,7 +208,7 @@ body > .container-fluid {
.savesequencemsg{
display: none;
text-align: center;
}
}
.notification {
background-color: #808b96;
@@ -244,35 +252,7 @@ a.name-header{
}
.step-column{
display:flex;
align-content: center;
justify-content: center;
}
.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;
display:flex;
align-content: center;
justify-content: center;
}

View File

@@ -1,9 +1,9 @@
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() {
sequencer = ImageSequencer();
@@ -12,21 +12,21 @@ window.onload = function() {
// 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,43 +59,48 @@ 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 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');
});
$('#download-btn').click(function() {
$('.step-thumbnail:last()').trigger("click");
return false;
});
function displayMessageOnSaveSequence(){
$('.savesequencemsg').fadeIn();
setTimeout(function() {
$('.savesequencemsg').fadeOut();
}, 1000);
}
$(".savesequencemsg").fadeIn();
setTimeout(function() {
$(".savesequencemsg").fadeOut();
}, 1000);
}
$('body').on('click', 'button.remove', ui.removeStepUi);
$('#save-seq').click(() => {
var result = window.prompt('Please give a name to your sequence... (Saved sequence will only be available in this browser).');
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)';
result = result + " (local)";
sequencer.saveSequence(result, sequencer.toString());
sequencer.loadModules();
displayMessageOnSaveSequence();
@@ -113,11 +118,11 @@ window.onload = function() {
var button = event.target;
button.disabled = true;
button.innerHTML = '<i class="fa fa-circle-o-notch fa-spin"></i>';
try {
// Select all images from previous steps
var imgs = document.getElementsByClassName('step-thumbnail');
var imgs = document.getElementsByClassName("step-thumbnail");
var imgSrcs = [];
@@ -130,7 +135,7 @@ window.onload = function() {
'gifHeight': imgs[0].height,
'images': imgSrcs,
'frameDuration': 7,
};
}
gifshot.createGIF(options, function(obj) {
if (!obj.error) {
@@ -138,21 +143,21 @@ window.onload = function() {
var image = obj.image;
var animatedImage = document.createElement('img');
animatedImage.id = 'gif_element';
animatedImage.id = "gif_element";
animatedImage.src = image;
var modal = $('#js-download-gif-modal');
$('#js-download-as-gif-button').one('click', function() {
$("#js-download-as-gif-button").one("click", function() {
// Trigger download
download(image, 'index.gif', 'image/gif');
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,7 +177,6 @@ window.onload = function() {
catch (e) {
console.error(e);
button.disabled = false;
button.innerHTML = 'View GIF';
isWorkingOnGifGeneration = false;
}
@@ -181,40 +184,40 @@ window.onload = 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

@@ -2,6 +2,7 @@
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -9,16 +10,12 @@
<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">
<!--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">
<title>Image Sequencer</title>
@@ -27,29 +24,25 @@
<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>
</head>
<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 +51,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 +60,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 +71,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 +83,82 @@
</section>
<hr />
<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;">
<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="center-align">
<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>
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button>
</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="row center-align">
<!--<button class="btn btn-primary btn-block btn-lg" name="save-sequence" id="save-seq">Save Sequence</button> -->
<!--<button class="btn btn-primary btn-block btn-lg" id="download-btn" name="download" style="display: block; margin: 0px 10px 0px 0px; width: 250px;">Download PNG</button> -->
<button class="btn btn-primary btn-block btn-lg js-view-as-gif" id="gif" style="margin: 0px 35px 0px 35px;width:100%;">View GIF</button>
</div>
<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,57 +176,61 @@
</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>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 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>
<p>Or click ARROW to save the entire sequence as a workflow for future use.</p>
<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>
<button id="saveButton" class="btn btn-primary btn-lg" style="margin-top:20px; margin-bottom:0px;align:center; width:100%;">Save</button>
</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>
Post a link to this and ask help from other community members on <a href="https://github.com/publiclab/image-sequencer/issues/new">Github Issues</a>
</p>
<p>
<a class="btn btn-primary" href="https://gitter.im/publiclab/publiclab">Ask a question on Gitter</a>
</p>
</div>
<div class="col-md-6">
<h2>Improve this tool</h2>
<p>
This is an open source toolkit which you can help add to and improve on <a href="https://github.com/publiclab/image-sequencer/">Github</a>
</p>
<p>
<a class="btn btn-primary" 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 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

@@ -16,8 +16,8 @@ var mapHtmlTypes = require('./mapHtmltypes');
function DefaultHtmlStepUi(_sequencer, options) {
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)
@@ -25,50 +25,46 @@ function DefaultHtmlStepUi(_sequencer, options) {
step.ui =
'\
<div class="container-fluid step-container">\
<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>\
<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>' +
'</p></div>\
</div>\
<div class="col-md-8 cal collapse in step-column">\
<div class="load load-spin" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<div class="step-image">\
<a class="cal collapse in"><img class="img-thumbnail step-thumbnail"/></a>\
</div>\
</div>\
</div>\
</div>\
<div class="panel-footer cal collapse in"></div>\
</form>\
</div>\
</div>';
<div class="container">\
<div class="row step">\
<form class="input-form">\
<div class="col-md-4 details">\
<h3>\
<span class = "toggle">' +step.name + ' <i class="fa fa-caret-up toggleIcon" aria-hidden="true"></i></span>' +
'<span class="load-spin" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></span>' +
'</h3><div class="cal collapse in"><p><i>"'+
(step.description || "") +
'</i></p></div>\
</div>\
</form>\
<div class="col-md-8 cal collapse in step-column">\
<div class="load" style="display:none;"><i class="fa fa-circle-o-notch fa-spin"></i></div>\
<div class="step-image">\
<a class="cal collapse in"><img alt="" class="img-thumbnail step-thumbnail"/></a>\
</div>\
</div>\
</div>\
</div>\
</div>';
var tools =
'<div class="trash">\
<button confirm="Are you sure?" class="remove btn btn-default btn-xs">\
<i class="fa fa-trash"></i>\
</button>\
'<div class="cal collapse in"><div class="tools btn-group">\
<button confirm="Are you sure?" class="remove btn btn btn-default">\
<i class="fa fa-trash"></i>\
</button>\
<button class="btn insert-step" style="margin-left:10px;border-radius:6px;background-color:#fff;border:solid #bababa 1.1px;" >\
<i class="fa fa-plus"></i> Add\
</button>\
</div>\
</div>';
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.linkElements = step.ui.querySelectorAll('a');
step.imgElement = step.ui.querySelector('a img.img-thumbnail');
step.ui = parser.parseFromString(step.ui, "text/html");
step.ui = step.ui.querySelector("div.container");
step.linkElements = step.ui.querySelectorAll("a");
step.imgElement = step.ui.querySelector("a img");
if (_sequencer.modulesInfo().hasOwnProperty(step.name)) {
var inputs = _sequencer.modulesInfo(step.name).inputs;
@@ -77,132 +73,110 @@ 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.ui.querySelector('div.details').appendChild(div);
"\
</div>";
step.ui.querySelector("div.details").appendChild(div);
}
$(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.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>'
$(step.ui.querySelector("div.details")).append(
'<div class="cal collapse in"><p><button type="submit" class="btn btn-default btn-save" disabled = "true" >Apply</button><span> Press apply to see changes</span></p></div>'
);
}
if (step.name != 'load-image') {
if (step.name != "load-image") {
step.ui
.querySelector('div.trash-container')
.prepend(
parser.parseFromString(tools, 'text/html').querySelector('div')
.querySelector("div.details")
.appendChild(
parser.parseFromString(tools, "text/html").querySelector("div")
);
$(step.ui.querySelectorAll('.remove')).on('click', function() {notify('Step Removed', 'remove-notification');});
$(step.ui.querySelectorAll('.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);
$("#steps .container:nth-last-child(1) .insert-step").prop('disabled',true);
if($("#steps .container:nth-last-child(2)"))
$("#steps .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.ui.querySelector('.toggle')).on('click', () => {
$(step.ui.querySelector('.toggleIcon')).toggleClass('rotated');
$(step.ui.querySelectorAll('.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(); });
$(step.ui.querySelectorAll('#color-picker')).colorpicker();
$(step.imgElement).on("mousemove", _.debounce(() => imageHover(step), 150));
function saveOptions(e) {
e.preventDefault();
if (optionsChanged){
$(step.ui.querySelector('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.ui.querySelector('.btn-save')).prop('disabled', true);
optionsChanged = false;
@@ -219,7 +193,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
return inputChanged;
}
var
var
changedInputs = 0,
optionsChanged = false;
$(step.ui.querySelector('.input-form')).on('submit', saveOptions);
@@ -227,7 +201,7 @@ function DefaultHtmlStepUi(_sequencer, options) {
$(input)
.data('initValue', $(input).val())
.data('hasChangedBefore', false)
.on('input change', function() {
.on('input', function() {
$(this)
.focus()
.data('hasChangedBefore',
@@ -235,32 +209,35 @@ 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) {
$(step.ui.querySelector('.load')).show();
$(step.ui.querySelector('img')).hide();
$(step.ui.querySelectorAll('.load-spin')).show();
$(step.ui.querySelector(".load")).show();
$(step.ui.querySelector("img")).hide();
if( $(step.ui.querySelector(".toggleIcon")).hasClass("fa-caret-down") )
{
$(step.ui.querySelector(".load-spin")).show();
}
}
function onComplete(step) {
$(step.ui.querySelector('img')).show();
$(step.ui.querySelectorAll('.load-spin')).hide();
$(step.ui.querySelector('.load')).hide();
$(step.ui.querySelector(".load")).hide();
$(step.ui.querySelector("img")).show();
$(step.ui.querySelector(".load-spin")).hide();
step.imgElement.src = (step.name == 'load-image') ? step.output.src : step.output;
var imgthumbnail = step.ui.querySelector('.img-thumbnail');
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;
@@ -268,24 +245,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];
}
$(step.ui.querySelectorAll('.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)) {
@@ -293,11 +260,11 @@ 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')
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')
if (inputs[i].type.toLowerCase() === "select")
$(step.ui.querySelector('div[name="' + i + '"] select'))
.val(step.options[i])
.data('initValue', step.options[i]);
@@ -315,24 +282,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 .container:nth-last-child(1) .insert-step").prop('disabled',true);
$('div[class*=imgareaselect-]').remove();
}
@@ -340,35 +307,35 @@ 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);
}
return {
getPreview: getPreview,
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,55 +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);
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);
}
});
}
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);
});
}
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,163 +1,135 @@
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="center-align">\
<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>\
<button class="btn btn-success btn-lg" name="add" id="add-step-btn">Add Step</button>\
</div>\
</div>\
</section>\
</div>\
</section>\
</div>';
}
function selectNewStepUi() {
var insertSelect = $(step.ui.querySelector('.insert-step-select'));
var m = insertSelect.val();
$(step.ui.querySelector('.insertDiv .info')).html(_sequencer.modulesInfo(m).description);
$(step.ui.querySelector('.insertDiv .add-step-btn')).prop('disabled', false);
var m = $("#insertStep select").val();
$("#insertStep .info").html(_sequencer.modulesInfo(m).description);
$("#insertStep #add-step-btn").prop("disabled", false);
}
var toggleDiv = function(callback = function(){}){
$(step.ui.querySelector('.insertDiv')).collapse('toggle');
if ($(step.ui.querySelector('.insert-text')).css('display') != 'none'){
$(step.ui.querySelector('.insert-text')).fadeToggle(200, function(){$(step.ui.querySelector('.no-insert-text')).fadeToggle(200, callback);});
}
else {
$(step.ui.querySelector('.no-insert-text')).fadeToggle(200, function(){$(step.ui.querySelector('.insert-text')).fadeToggle(200, callback);});
}
};
insertStep = function (id) {
var modulesInfo = _sequencer.modulesInfo();
var parser = new DOMParser();
var addStepUI = stepUI();
addStepUI = parser.parseFromString(addStepUI, 'text/html').querySelector('div');
if ($(step.ui.querySelector('.insertDiv')).length > 0){
toggleDiv();
}
else {
step.ui
.querySelector('div.step')
.insertAdjacentElement('afterend',
addStepUI
);
toggleDiv(function(){
insertPreview.updatePreviews(step.output, '.insertDiv');
});
}
$(step.ui.querySelector('.insertDiv .close-insert-box')).off('click').on('click', function(){toggleDiv(function(){});});
var insertStepSelect = $(step.ui.querySelector('.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.ui.querySelector('.inserDiv .add-step-btn')).prop('disabled', true);
insertStepSelect.append('<option value="" disabled selected>Select a Module</option>');
$(step.ui.querySelector('.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.ui.querySelector('.insert-step-select')).val(newStep);
insertStepSelect.val(newStep);
selectNewStepUi();
insert(id);
$(this).removeClass('selected');
});
insertStepSelect.on('change', selectNewStepUi);
$(step.ui.querySelector('.insertDiv .add-step-btn')).on('click', function () { insert(id); });
};
$(step.ui.querySelector("#insertStep select")).on('change', selectNewStepUi);
$(step.ui.querySelector("#insertStep #add-step-btn")).on('click', function () { insert(id) });
}
function insert(id) {
options = options || {};
var insertStepSelect = $(step.ui.querySelector('.insert-step-select'));
if (insertStepSelect.val() == 'none') return;
var insertStepSelect = $("#insertStep select");
if (insertStepSelect.val() == "none") return;
var newStepName = insertStepSelect.val();
toggleDiv();
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

@@ -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)
});

7338
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.0",
"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/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,73 +24,52 @@
"url": "https://github.com/publiclab/image-sequencer/issues"
},
"dependencies": {
"base64-img": "^1.0.4",
"bootstrap": "~3.4.0",
"bootstrap-colorpicker": "^2.5.3",
"buffer": "~5.2.1",
"commander": "^2.11.0",
"data-uri-to-buffer": "^2.0.0",
"downloadjs": "^1.4.7",
"eslint": "^5.16.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",
"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": "^13.1.0",
"jsqr": "^1.1.1",
"lodash": "^4.17.11",
"ndarray": "^1.0.18",
"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",
"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": "^5.16.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": "^8.1.6",
"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

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

View File

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

View File

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

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,29 +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 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]);
}
@@ -33,7 +34,7 @@ ImageSequencer = function ImageSequencer(options) {
}
function makeArray(input) {
return (objTypeOf(input) == 'Array') ? input : [input];
return (objTypeOf(input) == "Array") ? input : [input];
}
var image,
@@ -63,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;
}
@@ -86,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);
@@ -146,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,
@@ -168,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) {
@@ -197,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];
@@ -211,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) {
@@ -252,7 +371,7 @@ 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);
}
@@ -282,11 +401,9 @@ ImageSequencer = function ImageSequencer(options) {
this.sequences = require('./SavedSequences.json');
}
var str = require('./Strings.js')(this.steps, modulesInfo, addSteps, copy);
return {
//literals and objects
name: 'ImageSequencer',
name: "ImageSequencer",
options: options,
inputlog: inputlog,
modules: modules,
@@ -306,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'),
@@ -330,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

@@ -7,10 +7,8 @@ module.exports = {
'blend': require('./modules/Blend'),
'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'),
@@ -26,21 +24,17 @@ 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'),
'invert': require('image-sequencer-invert'),
'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')
};
}

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,48 +1,48 @@
module.exports = exports = function (options, pixels, oldPixels, callback) {
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) {
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))
}
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 {
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))
}
}
}
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,62 +1,84 @@
module.exports = exports = function(pixels, blur) {
let kernel = kernelGenerator(blur),
pixs = {
r: [],
g: [],
b: [],
};
let kernel = kernelGenerator(blur, 1), oldpix = require('lodash').cloneDeep(pixels);
kernel = flipKernel(kernel);
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++){
pixels.set(x, y, 0, Math.max(0, Math.min(conPix[0][y][x], 255)));
pixels.set(x, y, 1, Math.max(0, Math.min(conPix[1][y][x], 255)));
pixels.set(x, y, 2, Math.max(0, Math.min(conPix[2][y][x], 255)));
//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,64 +0,0 @@
/*
* Changes the Canvas Size
*/
module.exports = function canvasResize(options, UI) {
var defaults = require('./../../util/getDefaults.js')(require('./info.json'));
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;
newPixels.set(x, y, 0, pixels.get(i, j, 0));
newPixels.set(x, y, 1, pixels.get(i, j, 1));
newPixels.set(x, y, 2, pixels.get(i, j, 2));
newPixels.set(x, y, 3, pixels.get(i, j, 3));
}
}
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,83 +0,0 @@
module.exports = function ColorTemperature(options, UI) {
var output;
function draw(input, callback, progressObj) {
options.temperature = (options.temperature > '40000') ? '40000' : options.temperature;
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
function extraManipulation(pixels) {
let temp = parseInt(options.temperature);
temp /= 100;
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) {
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++) {
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 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,12 +0,0 @@
{
"name": "color-temperature",
"description": "Changes the color temperature of the image.",
"inputs": {
"temperature": {
"type": "integer",
"desc": "Temperature between 0 - 40,000 Kelvin",
"default": 6000
}
},
"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,47 +1,47 @@
var _ = require('lodash');
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 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;
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 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;
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);
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,50 +1,71 @@
var _ = require('lodash');
module.exports = exports = function(pixels, constantFactor, kernelValues, texMode) {
let kernel = kernelGenerator(constantFactor, kernelValues),
pixs = {
r: [],
g: [],
b: [],
};
module.exports = exports = function(pixels, constantFactor, kernelValues) {
let kernel = kernelGenerator(constantFactor, kernelValues), oldpix = _.cloneDeep(pixels);
kernel = flipKernel(kernel);
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++){
pixels.set(x, y, 0, Math.max(0, Math.min(conPix[0][y][x], 255)));
pixels.set(x, y, 1, Math.max(0, Math.min(conPix[1][y][x], 255)));
pixels.set(x, y, 2, Math.max(0, Math.min(conPix[2][y][x], 255)));
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')
]

View File

@@ -1,33 +1,33 @@
{
"name": "crop",
"name": "Crop",
"description": "Crop image to given x, y, w, h in pixels or % , measured from top left",
"url": "https://github.com/publiclab/image-sequencer/tree/master/MODULES.md",
"inputs": {
"x": {
"type": "string",
"type": "integer",
"desc": "X-position (measured from left) from where cropping starts",
"default": 0
},
"y": {
"type": "string",
"type": "integer",
"desc": "Y-position (measured from top) from where cropping starts",
"default": 0
},
"w": {
"type": "string",
"type": "integer",
"desc": "Width of crop",
"default": "(50%)"
},
"h": {
"type": "string",
"type": "integer",
"desc": "Height of crop",
"default": "(50%)"
},
"backgroundColor": {
"type": "text",
"desc": "Background Color",
"default": "rgba(255,255,255,255)",
"id": "color-picker"
"type": "string",
"desc": "Background Color (Four space separated RGBA values)",
"default": "255 255 255 255",
"placeholder": "255 255 255 255"
}
},
"docs-link":"https://github.com/publiclab/image-sequencer/blob/main/docs/MODULES.md#crop-module"

View File

@@ -1,34 +1,34 @@
/*
* Decodes QR from a given image.
*/
module.exports = function DoNothing(options, UI) {
module.exports = function DoNothing(options,UI) {
var output;
var jsQR = require('jsqr');
var getPixels = require('get-pixels');
// This function is called everytime a step has to be redrawn
function draw(input, callback, progressObj) {
function draw(input,callback,progressObj) {
progressObj.stop(true);
progressObj.overrideFlag = true;
var step = this;
getPixels(input.src, function(err, pixels) {
getPixels(input.src,function(err,pixels){
if (err) throw err;
if(err) throw err;
var w = pixels.shape[0];
var h = pixels.shape[1];
var decoded = jsQR(pixels.data, w, h);
var decoded = jsQR(pixels.data,w,h);
// Tell Image Sequencer that this step is complete
options.step.qrval = (decoded) ? decoded.data : 'undefined';
options.step.qrval = (decoded)?decoded.data:"undefined";
});
function output(image, datauri, mimetype) {
function output(image, datauri, mimetype){
// This output is accessible by Image Sequencer
step.output = {
src: datauri,
@@ -37,11 +37,9 @@ module.exports = function DoNothing(options, UI) {
}
return require('../_nomodule/PixelManipulation.js')(input, {
output: output,
ui: options.step.ui,
format: input.format,
image: options.image,
callback: callback,
useWasm:options.useWasm
callback: callback
});
}
@@ -51,5 +49,5 @@ module.exports = function DoNothing(options, UI) {
draw: draw,
output: output,
UI: UI
};
};
}
}

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