mirror of
https://github.com/publiclab/image-sequencer.git
synced 2025-12-13 20:00:05 +01:00
Resolve Conflicts; Update DecodeQr Module
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -34,3 +34,5 @@ node_modules
|
||||
|
||||
*.swp
|
||||
todo.txt
|
||||
test.js
|
||||
output.txt
|
||||
|
||||
40486
.source.1501282351926.0.9292555536537093.html
Normal file
40486
.source.1501282351926.0.9292555536537093.html
Normal file
File diff suppressed because one or more lines are too long
259
CONTRIBUTING.md
Normal file
259
CONTRIBUTING.md
Normal file
@@ -0,0 +1,259 @@
|
||||
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`.
|
||||
|
||||
Most contribution (we imagine) would be in the form of API-compatible modules, which need not be directly included.
|
||||
|
||||
## Contributing modules
|
||||
|
||||
Any module must look like this :
|
||||
|
||||
```js
|
||||
module.exports = function ModuleName(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Title of the Module";
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
UI.onDraw(options.step);
|
||||
|
||||
var output = /*do something with the input*/ ;
|
||||
|
||||
this.output = output;
|
||||
options.step.output = output.src;
|
||||
callback();
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
|
||||
return {
|
||||
options: options,
|
||||
draw: draw,
|
||||
output: output,
|
||||
UI: UI
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### options
|
||||
|
||||
The object `options` stores some important information. This is how you can accept
|
||||
input from users. If you require a variable "x" from the user and the user passes
|
||||
it in, you will be able to access it as `options.x`.
|
||||
|
||||
Options also has some in-built properties. The `options.inBrowser` boolean denotes
|
||||
whether your module is being run on a browser.
|
||||
|
||||
### draw()
|
||||
|
||||
The draw method is run every time the step is `run` using `sequencer.run()`.
|
||||
So any calculations must go **into** the `draw()` method's definition.
|
||||
|
||||
What is not in the draw method, but is in the `module.exports` is executed only
|
||||
when the step is added. So whatever external npm modules are to be loaded, or
|
||||
constant definitions must be done **outside** the `draw()` method's definition.
|
||||
|
||||
`draw()` receives two arguments - `input` and `callback` :
|
||||
* `input` is an object which is essentially the output of the previous step.
|
||||
```js
|
||||
input = {
|
||||
src: "<$DataURL>",
|
||||
format: "<png|jpeg|gif>"
|
||||
}
|
||||
```
|
||||
* `callback` is a function which is responsible to tell the sequencer that the
|
||||
step has been "drawn".
|
||||
|
||||
When you have done your calculations and produced an image output, you are required
|
||||
to set `this.output` to an object similar to what the input object was, call
|
||||
`callback()`, and set `options.step.output` equal to the output DataURL
|
||||
|
||||
### UI Methods
|
||||
|
||||
The module is responsible to emit various events for the UI to capture. There are
|
||||
four events in all:
|
||||
|
||||
* `UI.onSetup(options.step)` must be emitted when the module is added. So it must be emitted outside the draw method's definition as shown above.
|
||||
* `UI.onDraw(options.step)` must be emitted whenever the `draw()` method is called. So it should ideally be the first line of the definition of the `draw` method.
|
||||
* `UI.onComplete(options.step)` must be emitted whenever the output of a draw call
|
||||
is ready. An argument, that is the DataURL of the output image must be passed in.
|
||||
* `UI.onRemove(options.step)` is emitted automatically and the module should not emit it.
|
||||
|
||||
To add a module to Image Sequencer, it must have the following method; you can wrap an existing module to add them:
|
||||
|
||||
* `module.draw()`
|
||||
|
||||
The `draw(input,callback)` method should accept an `input` parameter, which will be an object of the form:
|
||||
|
||||
```js
|
||||
input = {
|
||||
src: "datauri here",
|
||||
format: "jpeg/png/etc"
|
||||
}
|
||||
```
|
||||
|
||||
## options.title
|
||||
|
||||
For display in the web-based UI, each module may also have a title `options.title`.
|
||||
|
||||
### Module example
|
||||
|
||||
See existing module `green-channel` for an example: https://github.com/publiclab/image-sequencer/tree/master/src/modules/GreenChannel/Module.js
|
||||
|
||||
For help integrating, please open an issue.
|
||||
|
||||
****
|
||||
|
||||
## Development
|
||||
|
||||
Notes on development next steps:
|
||||
|
||||
### UI
|
||||
|
||||
* [ ] add createUserInterface() which is set up by default to draw on ImageBoardUI, but could be swapped for nothing, or an equiv. lib
|
||||
* [ ] it could create the interface and use event listeners like module.on('draw', fn()); to update the interface
|
||||
|
||||
* [ ] spinners before panels are complete
|
||||
* [ ] is there a module for generating forms from parameters?
|
||||
* [ ] click to expand for all images
|
||||
* [ ] `ImageSequencer.Renderer` class to manage image output formats and adapters
|
||||
* [ ] remove step
|
||||
|
||||
* [ ] output besides an image -- like `message(txt)` to display to the step's UI
|
||||
|
||||
|
||||
### Modularization
|
||||
|
||||
* [ ] remotely includable modules, not compiled in -- see plugin structures in other libs
|
||||
* [x] ability to start running at any point -- already works?
|
||||
* [x] commandline runnability?
|
||||
* [x] Make available as browserified OR `require()` includable...
|
||||
* [ ] standardize panel addition with submodule that offers Panel.display(image)
|
||||
* [ ] allow passing data as data-uri or Image object, or stream, or ndarray or ImageData array, if both of neighboring pair has ability?
|
||||
* see https://github.com/jywarren/image-sequencer/issues/1
|
||||
* [ ] ...could we directly include package.json for module descriptions? At least as a fallback.
|
||||
* [ ] (for node-and-line style UIs) non-linear sequences with Y-splitters
|
||||
* [ ] `sequencer.addModule('path/to/module.js')` style module addition -- also to avoid browserifying all of Plotly :-P
|
||||
* [x] remove step
|
||||
|
||||
### Testing
|
||||
|
||||
* [x] tests - modules headless; unit tests
|
||||
* [ ] comparisons with diff
|
||||
* [ ] testing a module's promised functionality: each module could offer before/after images as part of their API; by running the module on the before image, you should get exactly the after image, comparing with an image diff
|
||||
|
||||
### Use cases
|
||||
|
||||
* [ ] make an Infragram module that accepts a math expression
|
||||
|
||||
### Bugs
|
||||
|
||||
* [x] BUG: this doesn't work for defaults: imageboard.loadImage('examples/grid.png', function() {});
|
||||
* we should make defaults a config of the first module
|
||||
|
||||
****
|
||||
|
||||
## Module Candidates
|
||||
|
||||
* https://github.com/linuxenko/rextract.js
|
||||
* https://www.npmjs.com/package/histogram
|
||||
* https://github.com/hughsk/flood-fill
|
||||
* https://www.npmjs.com/package/blink-diff
|
||||
* smaller and faster: https://www.npmjs.com/package/@schornio/pixelmatch
|
||||
* https://github.com/yahoo/pngjs-image has lots of useful general-purpose image getters like `image.getLuminosityAtIndex(idx)`
|
||||
* some way to add in a new image (respecting alpha) -- `add-image` (with blend mode, default `normal`?)
|
||||
* https://github.com/yuta1984/CannyJS - edge detection
|
||||
* http://codepen.io/taylorcoffelt/pen/EsCcr - more edge detection
|
||||
|
||||
## Ideas
|
||||
|
||||
* https://github.com/vicapow/jsqrcode
|
||||
* https://github.com/jadnco/whirl - scrubbable image sequence player
|
||||
* non graphics card GL functions could be shimmed with https://github.com/Overv/JSGL
|
||||
* or this: https://github.com/stackgl/headless-gl
|
||||
* https://github.com/mattdesl/fontpath-simple-renderer
|
||||
* output in animated Gif? as a module
|
||||
|
||||
### Referencing earlier states
|
||||
|
||||
Complex sequences with masking could require accessing previous states (or nonlinearity):
|
||||
|
||||
* flood-fill an area
|
||||
* select only the flooded area
|
||||
* roundabout: lighten everything to <50%, then flood-fill with black? Not 100% reliable.
|
||||
* roundabout 2: `flood fill`, then `blink-diff` with original
|
||||
* then add step which recovers original image, repeat `flood-fill`/`blink-diff` for second region
|
||||
* reference above masked states in a `mask` module, with `maskModule.draw(image, { getMask: function() { return maskImg } })`
|
||||
|
||||
****
|
||||
|
||||
**Notes:**
|
||||
|
||||
`pattern-fill` module to use patterns in JS canvas:
|
||||
|
||||
```js
|
||||
var c=document.getElementById("myCanvas");
|
||||
var ctx=c.getContext("2d");
|
||||
var img=document.getElementById("lamp");
|
||||
var pat=ctx.createPattern(img,"repeat");
|
||||
ctx.rect(0,0,150,100);
|
||||
ctx.fillStyle=pat;
|
||||
ctx.fill();
|
||||
```
|
||||
|
||||
Masking:
|
||||
|
||||
```js
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0);
|
||||
ctx.lineTo(160, 600);
|
||||
ctx.rect(0, 0, 160, 600);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
ctx.drawImage(img, 0, 0);
|
||||
ctx.restore();
|
||||
```
|
||||
|
||||
****
|
||||
|
||||
## UI notes:
|
||||
|
||||
* visual nodes-and-lines UI: https://github.com/flowhub/the-graph
|
||||
* https://flowhub.github.io/the-graph/examples/demo-simple.html
|
||||
|
||||
|
||||
|
||||
```js
|
||||
|
||||
settings: {
|
||||
'threshold': {
|
||||
type: 'slider',
|
||||
label: 'Threshold',
|
||||
default: 50,
|
||||
min: 0,
|
||||
max: 100
|
||||
},
|
||||
'colors': {
|
||||
type: 'select',
|
||||
label: 'Colors',
|
||||
options: [
|
||||
{ name: '0', value: '0', default: true },
|
||||
{ name: '1', value: '1' },
|
||||
{ name: '2', value: '2' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Possible web-based commandline interface: https://hyper.is/?
|
||||
|
||||
|
||||
### Path cutting
|
||||
|
||||
* threshold
|
||||
* vectorize
|
||||
* edge detect
|
||||
* direction find (vectorize and colorize)
|
||||
284
README.md
284
README.md
@@ -26,6 +26,14 @@ It is also for prototyping some other related ideas:
|
||||
* [Basic example](https://jywarren.github.io/image-sequencer/)
|
||||
* [NDVI example](https://jywarren.github.io/image-sequencer/examples/ndvi/) - related to [Infragram.org](http://infragram.org)
|
||||
|
||||
## Jump to:
|
||||
|
||||
* [Quick Usage](#quick-usage)
|
||||
* [Classic Usage](#classic-usage)
|
||||
* [Method Chaining](#method-chaining)
|
||||
* [Multiple Images](#multiple-images)
|
||||
* [Creating a User Interface](#creating-a-user-interface)
|
||||
|
||||
## Quick Usage
|
||||
|
||||
Image Sequencer can be used to run modules on an HTML Image Element using the
|
||||
@@ -68,11 +76,26 @@ a name and an image. The method also accepts an optional callback.
|
||||
```js
|
||||
sequencer.loadImage(image_src,optional_callback);
|
||||
```
|
||||
On `Node.js` the `image_src` may be a DataURI or a local path. On browsers, it
|
||||
must be a DatURI (or 'selector to image' -- Work in Progress)
|
||||
On `Node.js` the `image_src` may be a DataURI or a local path or a URL.
|
||||
|
||||
return value: **`sequencer`** (To allow method chaining)
|
||||
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
|
||||
|
||||
return value: **none** (A callback should be used to ensure the image gets loaded)
|
||||
The callback is called within the scope of a the sequencer. For example:
|
||||
(addSteps is defined later)
|
||||
|
||||
```js
|
||||
sequencer.loadImage('SRC',function(){
|
||||
this.addSteps('module-name');
|
||||
});
|
||||
```
|
||||
|
||||
The `this` refers to all the images added in the parent `loadImages` function only.
|
||||
In this case, only `'SRC'`.
|
||||
|
||||
### Adding steps to the image
|
||||
|
||||
@@ -156,6 +179,7 @@ return value: **`sequencer`** (To allow method chaining)
|
||||
|
||||
## Method Chaining
|
||||
Methods can be chained on the Image Sequencer:
|
||||
* loadImage()/loadImages() can only terminate a chain.
|
||||
* run() can not be in the middle of the chain.
|
||||
* If the chain starts with loadImage() or loadImages(), the following methods are
|
||||
applied only to the newly loaded images.
|
||||
@@ -164,9 +188,11 @@ be of the form "image<number>". For ex: "image1", "image2", "image3", etc.
|
||||
|
||||
Valid Chains:
|
||||
```js
|
||||
sequencer.loadImage('red').addSteps('invert').run(function(out){
|
||||
//do something with otuput.
|
||||
});
|
||||
sequencer.loadImage('red',function(){
|
||||
this.addSteps('invert').run(function(out){
|
||||
//do something with ouptut.
|
||||
});
|
||||
})
|
||||
sequencer.addSteps(['ndvi-red','invert']).run();
|
||||
et cetra.
|
||||
```
|
||||
@@ -209,7 +235,7 @@ with each image. This is a string literal.
|
||||
});
|
||||
```
|
||||
|
||||
return value: **`sequencer`** (To allow method chaining)
|
||||
return value: **none**
|
||||
|
||||
|
||||
### Adding Steps on Multiple Images
|
||||
@@ -344,10 +370,10 @@ How to define these functions:
|
||||
|
||||
```js
|
||||
sequencer.setUI({
|
||||
onSetup: function() {},
|
||||
onDraw: function() {},
|
||||
onComplete: function(output) {},
|
||||
onRemove: function() {}
|
||||
onSetup: function(step) {},
|
||||
onDraw: function(step) {},
|
||||
onComplete: function(step) {},
|
||||
onRemove: function(step) {}
|
||||
});
|
||||
```
|
||||
|
||||
@@ -357,220 +383,40 @@ the `setUI` method will only affect the modules added after `setUI` is called.
|
||||
|
||||
The `onComplete` event is passed on the output of the module.
|
||||
|
||||
In the scope of all these events, the following variables are present, which
|
||||
may be used in generating the UI:
|
||||
* The object `identity`
|
||||
```
|
||||
identity = {
|
||||
stepName: "Name of the Step",
|
||||
stepID: "A unique ID given to the step",
|
||||
imageName: "The name of the image to which the step is added."
|
||||
}
|
||||
```
|
||||
* The variable `options.inBrowser` which is a Boolean and is `true` if the client is a browser and `false` otherwise.
|
||||
Image Sequencer provides a namespace `step` for the purpose of UI Creation in
|
||||
the scope of these definable function. This namespace has the following
|
||||
predefined properties:
|
||||
|
||||
Note: `identity.imageName` is the "name" of that particular image. This name can be specified
|
||||
while loading the image via `sequencer.loadImage("name","SRC")`. If not specified,
|
||||
the name of a loaded image defaults to a name like "image1", "image2", et cetra.
|
||||
* `step.name` : (String) Name of the step
|
||||
* `step.ID` : (Number) An ID given to every step of the sequencer, unique throughout.
|
||||
* `step.imageName` : (String) Name of the image the step is applied to.
|
||||
* `step.output` : (DataURL String) Output of the step.
|
||||
* `step.inBrowser` : (Boolean) Whether the client is a browser or not
|
||||
|
||||
## Contributing
|
||||
In addition to these, one might define their own properties, which shall be
|
||||
accessible across all the event scopes of that step.
|
||||
|
||||
Happily accepting pull requests; to edit the core library, modify files in `/src/`. To build, run `npm install` and `grunt build`.
|
||||
|
||||
### Contributing modules
|
||||
|
||||
Most contribution (we imagine) would be in the form of API-compatible modules, which need not be directly included.
|
||||
|
||||
#### draw()
|
||||
|
||||
To add a module to Image Sequencer, it must have the following method; you can wrap an existing module to add them:
|
||||
|
||||
* `module.draw()`
|
||||
|
||||
The `draw(input,callback)` method should accept an `input` parameter, which will be an object of the form:
|
||||
For example :
|
||||
|
||||
```js
|
||||
input = {
|
||||
src: "datauri here",
|
||||
format: "jpeg/png/etc"
|
||||
}
|
||||
```
|
||||
|
||||
The `image` object is essentially the output of the previous step.
|
||||
|
||||
The draw method must, when it is complete, pass the output image to the method `this.output = modified_input`, which will send the output to the next module in the chain. For example:
|
||||
|
||||
```js
|
||||
function draw(image) {
|
||||
|
||||
// do some stuff with the image
|
||||
|
||||
this.output = image;
|
||||
callback();
|
||||
}
|
||||
```
|
||||
|
||||
#### Title
|
||||
|
||||
For display in the web-based UI, each module may also have a title like `options.title`.
|
||||
|
||||
#### Module example
|
||||
|
||||
See existing module `green-channel` for an example: https://github.com/jywarren/image-sequencer/tree/master/src/modules/GreenChannel.js
|
||||
|
||||
For help integrating, please open an issue.
|
||||
|
||||
****
|
||||
|
||||
## Development
|
||||
|
||||
Notes on development next steps:
|
||||
|
||||
### UI
|
||||
|
||||
* [ ] add createUserInterface() which is set up by default to draw on ImageBoardUI, but could be swapped for nothing, or an equiv. lib
|
||||
* [ ] it could create the interface and use event listeners like module.on('draw', fn()); to update the interface
|
||||
|
||||
* [ ] spinners before panels are complete
|
||||
* [ ] is there a module for generating forms from parameters?
|
||||
* [ ] click to expand for all images
|
||||
* [ ] `ImageSequencer.Renderer` class to manage image output formats and adapters
|
||||
* [ ] remove step
|
||||
|
||||
* [ ] output besides an image -- like `message(txt)` to display to the step's UI
|
||||
|
||||
|
||||
### Modularization
|
||||
|
||||
* [ ] remotely includable modules, not compiled in -- see plugin structures in other libs
|
||||
* [x] ability to start running at any point -- already works?
|
||||
* [x] commandline runnability?
|
||||
* [x] Make available as browserified OR `require()` includable...
|
||||
* [ ] standardize panel addition with submodule that offers Panel.display(image)
|
||||
* [ ] allow passing data as data-uri or Image object, or stream, or ndarray or ImageData array, if both of neighboring pair has ability?
|
||||
* see https://github.com/jywarren/image-sequencer/issues/1
|
||||
* [ ] ...could we directly include package.json for module descriptions? At least as a fallback.
|
||||
* [ ] (for node-and-line style UIs) non-linear sequences with Y-splitters
|
||||
* [ ] `sequencer.addModule('path/to/module.js')` style module addition -- also to avoid browserifying all of Plotly :-P
|
||||
* [x] remove step
|
||||
|
||||
### Testing
|
||||
|
||||
* [ ] tests - modules headless; unit tests
|
||||
* [ ] comparisons with diff
|
||||
* [ ] testing a module's promised functionality: each module could offer before/after images as part of their API; by running the module on the before image, you should get exactly the after image, comparing with an image diff
|
||||
|
||||
### Use cases
|
||||
|
||||
* [ ] make an Infragram module that accepts a math expression
|
||||
|
||||
### Bugs
|
||||
|
||||
* [x] BUG: this doesn't work for defaults: imageboard.loadImage('examples/grid.png', function() {});
|
||||
* we should make defaults a config of the first module
|
||||
|
||||
****
|
||||
|
||||
## Module Candidates
|
||||
|
||||
* https://github.com/linuxenko/rextract.js
|
||||
* https://www.npmjs.com/package/histogram
|
||||
* https://github.com/hughsk/flood-fill
|
||||
* https://www.npmjs.com/package/blink-diff
|
||||
* smaller and faster: https://www.npmjs.com/package/@schornio/pixelmatch
|
||||
* https://github.com/yahoo/pngjs-image has lots of useful general-purpose image getters like `image.getLuminosityAtIndex(idx)`
|
||||
* some way to add in a new image (respecting alpha) -- `add-image` (with blend mode, default `normal`?)
|
||||
* https://github.com/yuta1984/CannyJS - edge detection
|
||||
* http://codepen.io/taylorcoffelt/pen/EsCcr - more edge detection
|
||||
|
||||
## Ideas
|
||||
|
||||
* https://github.com/vicapow/jsqrcode
|
||||
* https://github.com/jadnco/whirl - scrubbable image sequence player
|
||||
* non graphics card GL functions could be shimmed with https://github.com/Overv/JSGL
|
||||
* or this: https://github.com/stackgl/headless-gl
|
||||
* https://github.com/mattdesl/fontpath-simple-renderer
|
||||
* output in animated Gif? as a module
|
||||
|
||||
### Referencing earlier states
|
||||
|
||||
Complex sequences with masking could require accessing previous states (or nonlinearity):
|
||||
|
||||
* flood-fill an area
|
||||
* select only the flooded area
|
||||
* roundabout: lighten everything to <50%, then flood-fill with black? Not 100% reliable.
|
||||
* roundabout 2: `flood fill`, then `blink-diff` with original
|
||||
* then add step which recovers original image, repeat `flood-fill`/`blink-diff` for second region
|
||||
* reference above masked states in a `mask` module, with `maskModule.draw(image, { getMask: function() { return maskImg } })`
|
||||
|
||||
****
|
||||
|
||||
**Notes:**
|
||||
|
||||
`pattern-fill` module to use patterns in JS canvas:
|
||||
|
||||
```js
|
||||
var c=document.getElementById("myCanvas");
|
||||
var ctx=c.getContext("2d");
|
||||
var img=document.getElementById("lamp");
|
||||
var pat=ctx.createPattern(img,"repeat");
|
||||
ctx.rect(0,0,150,100);
|
||||
ctx.fillStyle=pat;
|
||||
ctx.fill();
|
||||
```
|
||||
|
||||
Masking:
|
||||
|
||||
```js
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0);
|
||||
ctx.lineTo(160, 600);
|
||||
ctx.rect(0, 0, 160, 600);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
ctx.drawImage(img, 0, 0);
|
||||
ctx.restore();
|
||||
```
|
||||
|
||||
****
|
||||
|
||||
## UI notes:
|
||||
|
||||
* visual nodes-and-lines UI: https://github.com/flowhub/the-graph
|
||||
* https://flowhub.github.io/the-graph/examples/demo-simple.html
|
||||
|
||||
|
||||
|
||||
```js
|
||||
|
||||
settings: {
|
||||
'threshold': {
|
||||
type: 'slider',
|
||||
label: 'Threshold',
|
||||
default: 50,
|
||||
min: 0,
|
||||
max: 100
|
||||
sequencer.setUI({
|
||||
onSetup: function(step){
|
||||
// Create new property "step.image"
|
||||
step.image = document.createElement('img');
|
||||
document.body.append(step.image);
|
||||
},
|
||||
'colors': {
|
||||
type: 'select',
|
||||
label: 'Colors',
|
||||
options: [
|
||||
{ name: '0', value: '0', default: true },
|
||||
{ name: '1', value: '1' },
|
||||
{ name: '2', value: '2' }
|
||||
]
|
||||
onComplete: function(step){
|
||||
// Access predefined "step.output" and user-defined "step.image"
|
||||
step.image.src = step.output;
|
||||
},
|
||||
onRemove: function(step){
|
||||
// Access user-defined "step.image"
|
||||
step.image.remove();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
Possible web-based commandline interface: https://hyper.is/?
|
||||
|
||||
|
||||
### Path cutting
|
||||
|
||||
* threshold
|
||||
* vectorize
|
||||
* edge detect
|
||||
* direction find (vectorize and colorize)
|
||||
Note: `identity.imageName` is the "name" of that particular image. This name can
|
||||
be specified while loading the image via `sequencer.loadImage("name","SRC")`. If
|
||||
not specified, the name of a loaded image defaults to a name like "image1",
|
||||
"image2", et cetra.
|
||||
|
||||
247
dist/image-sequencer.js
vendored
247
dist/image-sequencer.js
vendored
@@ -37117,11 +37117,14 @@ function AddStep(ref, image, name, o) {
|
||||
o.container = o_.container || ref.options.selector;
|
||||
o.image = image;
|
||||
|
||||
var UI = ref.UI({
|
||||
stepName: o.name,
|
||||
stepID: o.number,
|
||||
imageName: o.image
|
||||
});
|
||||
o.step = {
|
||||
name: o.name,
|
||||
ID: o.number,
|
||||
imageName: o.image,
|
||||
inBrowser: ref.options.inBrowser,
|
||||
ui: ref.options.ui
|
||||
};
|
||||
var UI = ref.events;
|
||||
var module = ref.modules[name](o,UI);
|
||||
ref.images[image].steps.push(module);
|
||||
|
||||
@@ -37343,9 +37346,7 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
formatInput = require('./FormatInput'),
|
||||
images = {},
|
||||
inputlog = [],
|
||||
UI;
|
||||
|
||||
setUI();
|
||||
events = require('./UserInterface')();
|
||||
|
||||
// if in browser, prompt for an image
|
||||
// if (options.imageSelect || options.inBrowser) addStep('image-select');
|
||||
@@ -37370,7 +37371,8 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
function removeStep(image,index) {
|
||||
//remove the step from images[image].steps and redraw remaining images
|
||||
if(index>0) {
|
||||
images[image].steps[index].UI.onRemove();
|
||||
thisStep = images[image].steps[index];
|
||||
thisStep.UI.onRemove(thisStep.options.step);
|
||||
images[image].steps.splice(index,1);
|
||||
}
|
||||
//tell the UI a step has been removed
|
||||
@@ -37434,17 +37436,15 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
|
||||
function loadImages() {
|
||||
var args = [];
|
||||
var sequencer = this;
|
||||
for (var arg in arguments) args.push(copy(arguments[arg]));
|
||||
var json_q = formatInput.call(this,args,"l");
|
||||
|
||||
inputlog.push({method:"loadImages", json_q:copy(json_q)});
|
||||
var loadedimages = this.copy(json_q.loadedimages);
|
||||
// require('./LoadImage')(this,i,json_q.images[i]);
|
||||
|
||||
for (var i in json_q.images)
|
||||
require('./LoadImage')(this,i,json_q.images[i])
|
||||
|
||||
json_q.callback();
|
||||
return {
|
||||
var ret = {
|
||||
name: "ImageSequencer Wrapper",
|
||||
sequencer: this,
|
||||
addSteps: this.addSteps,
|
||||
@@ -37455,6 +37455,19 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
setUI: this.setUI,
|
||||
images: loadedimages
|
||||
};
|
||||
|
||||
function load(i) {
|
||||
if(i==loadedimages.length) {
|
||||
json_q.callback.call(ret);
|
||||
return;
|
||||
}
|
||||
var img = loadedimages[i];
|
||||
require('./LoadImage')(sequencer,img,json_q.images[img],function(){
|
||||
load(++i);
|
||||
});
|
||||
}
|
||||
|
||||
load(0);
|
||||
}
|
||||
|
||||
function replaceImage(selector,steps,options) {
|
||||
@@ -37462,9 +37475,8 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
return require('./ReplaceImage')(this,selector,steps);
|
||||
}
|
||||
|
||||
function setUI(_UI) {
|
||||
UI = require('./UserInterface')(_UI,options);
|
||||
return UI;
|
||||
function setUI(UI) {
|
||||
this.events = require('./UserInterface')(UI);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -37474,7 +37486,7 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
inputlog: inputlog,
|
||||
modules: modules,
|
||||
images: images,
|
||||
UI: UI,
|
||||
events: events,
|
||||
|
||||
//user functions
|
||||
loadImages: loadImages,
|
||||
@@ -37508,11 +37520,14 @@ function InsertStep(ref, image, index, name, o) {
|
||||
|
||||
if(index==-1) index = ref.images[image].steps.length;
|
||||
|
||||
var UI = ref.UI({
|
||||
stepName: o.name,
|
||||
stepID: o.number,
|
||||
imageName: o.image
|
||||
});
|
||||
o.step = {
|
||||
name: o.name,
|
||||
ID: o.number,
|
||||
imageName: o.image,
|
||||
inBrowser: ref.options.inBrowser,
|
||||
ui: ref.options.ui
|
||||
};
|
||||
var UI = ref.events;
|
||||
var module = ref.modules[name](o,UI);
|
||||
ref.images[image].steps.splice(index,0,module);
|
||||
|
||||
@@ -37524,49 +37539,102 @@ function InsertStep(ref, image, index, name, o) {
|
||||
module.exports = InsertStep;
|
||||
|
||||
},{}],116:[function(require,module,exports){
|
||||
function LoadImage(ref, name, src) {
|
||||
function CImage(src) {
|
||||
var datauri = (ref.options.inBrowser || src.substring(0,11) == "data:image/")?(src):require('urify')(src);
|
||||
function LoadImage(ref, name, src, main_callback) {
|
||||
function makeImage(datauri) {
|
||||
var image = {
|
||||
src: datauri,
|
||||
format: datauri.split(':')[1].split(';')[0].split('/')[1]
|
||||
}
|
||||
return image;
|
||||
}
|
||||
function CImage(src, callback) {
|
||||
var datauri;
|
||||
if (!!src.match(/^data:/i)) {
|
||||
datauri = src;
|
||||
callback(datauri);
|
||||
}
|
||||
else if (!ref.options.inBrowser && !!src.match(/^https?:\/\//i)) {
|
||||
require( src.match(/^(https?):\/\//i)[1] ).get(src,function(res){
|
||||
var data = '';
|
||||
var contentType = res.headers['content-type'];
|
||||
res.setEncoding('base64');
|
||||
res.on('data',function(chunk) {data += chunk;});
|
||||
res.on('end',function() {
|
||||
callback("data:"+contentType+";base64,"+data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (ref.options.inBrowser) {
|
||||
var ext = src.split('.').pop();
|
||||
var image = document.createElement('img');
|
||||
var canvas = document.createElement('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
image.onload = function() {
|
||||
canvas.width = image.naturalWidth;
|
||||
canvas.height = image.naturalHeight;
|
||||
context.drawImage(image,0,0);
|
||||
datauri = canvas.toDataURL(ext);
|
||||
callback(datauri);
|
||||
}
|
||||
image.src = src;
|
||||
}
|
||||
else {
|
||||
datauri = require('urify')(src);
|
||||
callback(datauri);
|
||||
}
|
||||
}
|
||||
|
||||
function loadImage(name, src) {
|
||||
var step = {
|
||||
name: "load-image",
|
||||
ID: ref.options.sequencerCounter++,
|
||||
imageName: name,
|
||||
inBrowser: ref.options.inBrowser,
|
||||
ui: ref.options.ui
|
||||
};
|
||||
|
||||
var image = {
|
||||
src: src,
|
||||
steps: [{
|
||||
options: {
|
||||
id: ref.options.sequencerCounter++,
|
||||
id: step.ID,
|
||||
name: "load-image",
|
||||
title: "Load Image"
|
||||
title: "Load Image",
|
||||
step: step
|
||||
},
|
||||
UI: ref.UI({
|
||||
stepName: "load-image",
|
||||
stepID: ref.options.sequencerCounter++,
|
||||
imageName: name
|
||||
}),
|
||||
UI: ref.events,
|
||||
draw: function() {
|
||||
UI.onDraw(options.step);
|
||||
if(arguments.length==1){
|
||||
this.output = CImage(arguments[0]);
|
||||
options.step.output = this.output;
|
||||
UI.onComplete(options.step);
|
||||
return true;
|
||||
}
|
||||
else if(arguments.length==2) {
|
||||
this.output = CImage(arguments[0]);
|
||||
options.step.output = this.output;
|
||||
arguments[1]();
|
||||
UI.onComplete(options.step);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
output: CImage(src)
|
||||
}]
|
||||
};
|
||||
CImage(src, function(datauri) {
|
||||
var output = makeImage(datauri);
|
||||
ref.images[name] = image;
|
||||
ref.images[name].steps[0].UI.onSetup();
|
||||
ref.images[name].steps[0].UI.onDraw();
|
||||
ref.images[name].steps[0].UI.onComplete(image.steps[0].output.src);
|
||||
var loadImageStep = ref.images[name].steps[0];
|
||||
loadImageStep.output = output;
|
||||
loadImageStep.options.step.output = loadImageStep.output.src;
|
||||
loadImageStep.UI.onSetup(loadImageStep.options.step);
|
||||
loadImageStep.UI.onDraw(loadImageStep.options.step);
|
||||
loadImageStep.UI.onComplete(loadImageStep.options.step);
|
||||
|
||||
main_callback();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return loadImage(name,src);
|
||||
@@ -37677,75 +37745,69 @@ module.exports = Run;
|
||||
|
||||
},{}],120:[function(require,module,exports){
|
||||
/*
|
||||
* Default UI for each image-sequencer module
|
||||
* User Interface Handling Module
|
||||
*/
|
||||
module.exports = function UserInterface(UI,options) {
|
||||
|
||||
return function userInterface(identity) {
|
||||
module.exports = function UserInterface(events = {}) {
|
||||
|
||||
var UI = UI || {};
|
||||
|
||||
UI.onSetup = UI.onSetup || function() {
|
||||
if(options.ui == false) {
|
||||
events.onSetup = events.onSetup || function(step) {
|
||||
if(step.ui == false) {
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Create and append an HTML Element
|
||||
console.log("Added Step \""+identity.stepName+"\" to \""+identity.imageName+"\".");
|
||||
console.log("Added Step \""+step.name+"\" to \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Create a NodeJS Object
|
||||
console.log('\x1b[36m%s\x1b[0m',"Added Step \""+identity.stepName+"\" to \""+identity.imageName+"\".");
|
||||
|
||||
console.log('\x1b[36m%s\x1b[0m',"Added Step \""+step.name+"\" to \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
UI.onDraw = UI.onDraw || function() {
|
||||
if (options.ui == false) {
|
||||
events.onDraw = events.onDraw || function(step) {
|
||||
if (step.ui == false) {
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Overlay a loading spinner
|
||||
console.log("Drawing Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log("Drawing Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Don't do anything
|
||||
console.log('\x1b[33m%s\x1b[0m',"Drawing Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log('\x1b[33m%s\x1b[0m',"Drawing Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
UI.onComplete = UI.onComplete || function(output) {
|
||||
if (options.ui == false) {
|
||||
events.onComplete = events.onComplete || function(step) {
|
||||
if (step.ui == false) {
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Update the DIV Element
|
||||
// Hide the laoding spinner
|
||||
console.log("Drawn Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log("Drawn Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Update the NodeJS Object
|
||||
console.log('\x1b[32m%s\x1b[0m',"Drawn Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log('\x1b[32m%s\x1b[0m',"Drawn Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
UI.onRemove = UI.onRemove || function(callback) {
|
||||
if(options.ui == false){
|
||||
events.onRemove = events.onRemove || function(step) {
|
||||
if(step.ui == false){
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Remove the DIV Element
|
||||
console.log("Removing Step \""+identity.stepName+"\" of \""+identity.imageName+"\".");
|
||||
console.log("Removing Step \""+step.name+"\" of \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Delete the NodeJS Object
|
||||
console.log('\x1b[31m%s\x1b[0m',"Removing Step \""+identity.stepName+"\" of \""+identity.imageName+"\".");
|
||||
console.log('\x1b[31m%s\x1b[0m',"Removing Step \""+step.name+"\" of \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
return UI;
|
||||
|
||||
}
|
||||
return events;
|
||||
|
||||
}
|
||||
|
||||
@@ -37809,12 +37871,12 @@ module.exports = function Crop(input,options,callback) {
|
||||
module.exports = function CropModule(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Crop Image";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
require('./Crop')(input,options,function(out,format){
|
||||
@@ -37822,7 +37884,8 @@ module.exports = function Crop(input,options,callback) {
|
||||
src: out,
|
||||
format: format
|
||||
}
|
||||
UI.onComplete(out);
|
||||
options.step.output = out;
|
||||
UI.onComplete(options.step);
|
||||
callback();
|
||||
});
|
||||
|
||||
@@ -37880,14 +37943,17 @@ module.exports = function DoNothing(options,UI) {
|
||||
module.exports = function DoNothing(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Do Nothing";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
|
||||
this.output = input;
|
||||
|
||||
options.step.output = this.output.src;
|
||||
callback();
|
||||
UI.onComplete(this.output.src);
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -37906,12 +37972,12 @@ module.exports = function DoNothingPix(options,UI) {
|
||||
|
||||
options = options || {};
|
||||
options.title = "Do Nothing with pixels";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -37919,7 +37985,8 @@ module.exports = function DoNothingPix(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype}
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
@@ -37948,12 +38015,12 @@ module.exports = function GreenChannel(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Green channel only";
|
||||
options.description = "Displays only the green channel of an image";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -37961,7 +38028,8 @@ module.exports = function GreenChannel(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
@@ -37991,14 +38059,14 @@ module.exports = function GreenChannel(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Invert Colors";
|
||||
options.description = "Inverts the colors of the image";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
//function setup() {} // optional
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -38006,7 +38074,8 @@ module.exports = function GreenChannel(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
@@ -38035,12 +38104,12 @@ module.exports = function NdviRed(options,UI) {
|
||||
|
||||
options = options || {};
|
||||
options.title = "NDVI for red-filtered cameras (blue is infrared)";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -38050,7 +38119,8 @@ module.exports = function NdviRed(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
@@ -38075,12 +38145,12 @@ module.exports = function SegmentedColormap(options,UI) {
|
||||
|
||||
options = options || {};
|
||||
options.title = "Segmented Colormap";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -38091,7 +38161,8 @@ module.exports = function SegmentedColormap(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
@@ -38217,7 +38288,7 @@ module.exports = function PixelManipulation(image, options) {
|
||||
// but node modules and their documentation are essentially arcane on this point
|
||||
var chunks = [];
|
||||
var totalLength = 0;
|
||||
var r = savePixels(pixels, options.format);
|
||||
var r = savePixels(pixels, options.format, {quality: 100});
|
||||
|
||||
r.on('data', function(chunk){
|
||||
totalLength += chunk.length;
|
||||
|
||||
BIN
examples/red.png
Normal file
BIN
examples/red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 277 B |
BIN
examples/test.gif
Normal file
BIN
examples/test.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
1
examples/test.gif.js
Normal file
1
examples/test.gif.js
Normal file
File diff suppressed because one or more lines are too long
1
examples/test.png.js
Normal file
1
examples/test.png.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "image-sequencer",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.0",
|
||||
"description": "A modular JavaScript image manipulation library modeled on a storyboard.",
|
||||
"main": "dist/image-sequencer.js",
|
||||
"main": "src/ImageSequencer.js",
|
||||
"scripts": {
|
||||
"test": "tape test/*.js | tap-spec; browserify test/image-sequencer.js test/chain.js | tape-run --render=\"tap-spec\""
|
||||
},
|
||||
|
||||
@@ -8,11 +8,14 @@ function AddStep(ref, image, name, o) {
|
||||
o.container = o_.container || ref.options.selector;
|
||||
o.image = image;
|
||||
|
||||
var UI = ref.UI({
|
||||
stepName: o.name,
|
||||
stepID: o.number,
|
||||
imageName: o.image
|
||||
});
|
||||
o.step = {
|
||||
name: o.name,
|
||||
ID: o.number,
|
||||
imageName: o.image,
|
||||
inBrowser: ref.options.inBrowser,
|
||||
ui: ref.options.ui
|
||||
};
|
||||
var UI = ref.events;
|
||||
var module = ref.modules[name](o,UI);
|
||||
ref.images[image].steps.push(module);
|
||||
|
||||
|
||||
@@ -42,9 +42,7 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
formatInput = require('./FormatInput'),
|
||||
images = {},
|
||||
inputlog = [],
|
||||
UI;
|
||||
|
||||
setUI();
|
||||
events = require('./UserInterface')();
|
||||
|
||||
// if in browser, prompt for an image
|
||||
// if (options.imageSelect || options.inBrowser) addStep('image-select');
|
||||
@@ -69,7 +67,8 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
function removeStep(image,index) {
|
||||
//remove the step from images[image].steps and redraw remaining images
|
||||
if(index>0) {
|
||||
images[image].steps[index].UI.onRemove();
|
||||
thisStep = images[image].steps[index];
|
||||
thisStep.UI.onRemove(thisStep.options.step);
|
||||
images[image].steps.splice(index,1);
|
||||
}
|
||||
//tell the UI a step has been removed
|
||||
@@ -133,17 +132,15 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
|
||||
function loadImages() {
|
||||
var args = [];
|
||||
var sequencer = this;
|
||||
for (var arg in arguments) args.push(copy(arguments[arg]));
|
||||
var json_q = formatInput.call(this,args,"l");
|
||||
|
||||
inputlog.push({method:"loadImages", json_q:copy(json_q)});
|
||||
var loadedimages = this.copy(json_q.loadedimages);
|
||||
// require('./LoadImage')(this,i,json_q.images[i]);
|
||||
|
||||
for (var i in json_q.images)
|
||||
require('./LoadImage')(this,i,json_q.images[i])
|
||||
|
||||
json_q.callback();
|
||||
return {
|
||||
var ret = {
|
||||
name: "ImageSequencer Wrapper",
|
||||
sequencer: this,
|
||||
addSteps: this.addSteps,
|
||||
@@ -154,6 +151,19 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
setUI: this.setUI,
|
||||
images: loadedimages
|
||||
};
|
||||
|
||||
function load(i) {
|
||||
if(i==loadedimages.length) {
|
||||
json_q.callback.call(ret);
|
||||
return;
|
||||
}
|
||||
var img = loadedimages[i];
|
||||
require('./LoadImage')(sequencer,img,json_q.images[img],function(){
|
||||
load(++i);
|
||||
});
|
||||
}
|
||||
|
||||
load(0);
|
||||
}
|
||||
|
||||
function replaceImage(selector,steps,options) {
|
||||
@@ -161,9 +171,8 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
return require('./ReplaceImage')(this,selector,steps);
|
||||
}
|
||||
|
||||
function setUI(_UI) {
|
||||
UI = require('./UserInterface')(_UI,options);
|
||||
return UI;
|
||||
function setUI(UI) {
|
||||
this.events = require('./UserInterface')(UI);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -173,7 +182,7 @@ ImageSequencer = function ImageSequencer(options) {
|
||||
inputlog: inputlog,
|
||||
modules: modules,
|
||||
images: images,
|
||||
UI: UI,
|
||||
events: events,
|
||||
|
||||
//user functions
|
||||
loadImages: loadImages,
|
||||
|
||||
@@ -10,11 +10,14 @@ function InsertStep(ref, image, index, name, o) {
|
||||
|
||||
if(index==-1) index = ref.images[image].steps.length;
|
||||
|
||||
var UI = ref.UI({
|
||||
stepName: o.name,
|
||||
stepID: o.number,
|
||||
imageName: o.image
|
||||
});
|
||||
o.step = {
|
||||
name: o.name,
|
||||
ID: o.number,
|
||||
imageName: o.image,
|
||||
inBrowser: ref.options.inBrowser,
|
||||
ui: ref.options.ui
|
||||
};
|
||||
var UI = ref.events;
|
||||
var module = ref.modules[name](o,UI);
|
||||
ref.images[image].steps.splice(index,0,module);
|
||||
|
||||
|
||||
@@ -1,46 +1,99 @@
|
||||
function LoadImage(ref, name, src) {
|
||||
function CImage(src) {
|
||||
var datauri = (ref.options.inBrowser || src.substring(0,11) == "data:image/")?(src):require('urify')(src);
|
||||
function LoadImage(ref, name, src, main_callback) {
|
||||
function makeImage(datauri) {
|
||||
var image = {
|
||||
src: datauri,
|
||||
format: datauri.split(':')[1].split(';')[0].split('/')[1]
|
||||
}
|
||||
return image;
|
||||
}
|
||||
function CImage(src, callback) {
|
||||
var datauri;
|
||||
if (!!src.match(/^data:/i)) {
|
||||
datauri = src;
|
||||
callback(datauri);
|
||||
}
|
||||
else if (!ref.options.inBrowser && !!src.match(/^https?:\/\//i)) {
|
||||
require( src.match(/^(https?):\/\//i)[1] ).get(src,function(res){
|
||||
var data = '';
|
||||
var contentType = res.headers['content-type'];
|
||||
res.setEncoding('base64');
|
||||
res.on('data',function(chunk) {data += chunk;});
|
||||
res.on('end',function() {
|
||||
callback("data:"+contentType+";base64,"+data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (ref.options.inBrowser) {
|
||||
var ext = src.split('.').pop();
|
||||
var image = document.createElement('img');
|
||||
var canvas = document.createElement('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
image.onload = function() {
|
||||
canvas.width = image.naturalWidth;
|
||||
canvas.height = image.naturalHeight;
|
||||
context.drawImage(image,0,0);
|
||||
datauri = canvas.toDataURL(ext);
|
||||
callback(datauri);
|
||||
}
|
||||
image.src = src;
|
||||
}
|
||||
else {
|
||||
datauri = require('urify')(src);
|
||||
callback(datauri);
|
||||
}
|
||||
}
|
||||
|
||||
function loadImage(name, src) {
|
||||
var step = {
|
||||
name: "load-image",
|
||||
ID: ref.options.sequencerCounter++,
|
||||
imageName: name,
|
||||
inBrowser: ref.options.inBrowser,
|
||||
ui: ref.options.ui
|
||||
};
|
||||
|
||||
var image = {
|
||||
src: src,
|
||||
steps: [{
|
||||
options: {
|
||||
id: ref.options.sequencerCounter++,
|
||||
id: step.ID,
|
||||
name: "load-image",
|
||||
title: "Load Image"
|
||||
title: "Load Image",
|
||||
step: step
|
||||
},
|
||||
UI: ref.UI({
|
||||
stepName: "load-image",
|
||||
stepID: ref.options.sequencerCounter++,
|
||||
imageName: name
|
||||
}),
|
||||
UI: ref.events,
|
||||
draw: function() {
|
||||
UI.onDraw(options.step);
|
||||
if(arguments.length==1){
|
||||
this.output = CImage(arguments[0]);
|
||||
options.step.output = this.output;
|
||||
UI.onComplete(options.step);
|
||||
return true;
|
||||
}
|
||||
else if(arguments.length==2) {
|
||||
this.output = CImage(arguments[0]);
|
||||
options.step.output = this.output;
|
||||
arguments[1]();
|
||||
UI.onComplete(options.step);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
output: CImage(src)
|
||||
}]
|
||||
};
|
||||
CImage(src, function(datauri) {
|
||||
var output = makeImage(datauri);
|
||||
ref.images[name] = image;
|
||||
ref.images[name].steps[0].UI.onSetup();
|
||||
ref.images[name].steps[0].UI.onDraw();
|
||||
ref.images[name].steps[0].UI.onComplete(image.steps[0].output.src);
|
||||
var loadImageStep = ref.images[name].steps[0];
|
||||
loadImageStep.output = output;
|
||||
loadImageStep.options.step.output = loadImageStep.output.src;
|
||||
loadImageStep.UI.onSetup(loadImageStep.options.step);
|
||||
loadImageStep.UI.onDraw(loadImageStep.options.step);
|
||||
loadImageStep.UI.onComplete(loadImageStep.options.step);
|
||||
|
||||
main_callback();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return loadImage(name,src);
|
||||
|
||||
@@ -1,72 +1,66 @@
|
||||
/*
|
||||
* Default UI for each image-sequencer module
|
||||
* User Interface Handling Module
|
||||
*/
|
||||
module.exports = function UserInterface(UI,options) {
|
||||
|
||||
return function userInterface(identity) {
|
||||
module.exports = function UserInterface(events = {}) {
|
||||
|
||||
var UI = UI || {};
|
||||
|
||||
UI.onSetup = UI.onSetup || function() {
|
||||
if(options.ui == false) {
|
||||
events.onSetup = events.onSetup || function(step) {
|
||||
if(step.ui == false) {
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Create and append an HTML Element
|
||||
console.log("Added Step \""+identity.stepName+"\" to \""+identity.imageName+"\".");
|
||||
console.log("Added Step \""+step.name+"\" to \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Create a NodeJS Object
|
||||
console.log('\x1b[36m%s\x1b[0m',"Added Step \""+identity.stepName+"\" to \""+identity.imageName+"\".");
|
||||
|
||||
console.log('\x1b[36m%s\x1b[0m',"Added Step \""+step.name+"\" to \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
UI.onDraw = UI.onDraw || function() {
|
||||
if (options.ui == false) {
|
||||
events.onDraw = events.onDraw || function(step) {
|
||||
if (step.ui == false) {
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Overlay a loading spinner
|
||||
console.log("Drawing Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log("Drawing Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Don't do anything
|
||||
console.log('\x1b[33m%s\x1b[0m',"Drawing Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log('\x1b[33m%s\x1b[0m',"Drawing Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
UI.onComplete = UI.onComplete || function(output) {
|
||||
if (options.ui == false) {
|
||||
events.onComplete = events.onComplete || function(step) {
|
||||
if (step.ui == false) {
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Update the DIV Element
|
||||
// Hide the laoding spinner
|
||||
console.log("Drawn Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log("Drawn Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Update the NodeJS Object
|
||||
console.log('\x1b[32m%s\x1b[0m',"Drawn Step \""+identity.stepName+"\" on \""+identity.imageName+"\".");
|
||||
console.log('\x1b[32m%s\x1b[0m',"Drawn Step \""+step.name+"\" on \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
UI.onRemove = UI.onRemove || function(callback) {
|
||||
if(options.ui == false){
|
||||
events.onRemove = events.onRemove || function(step) {
|
||||
if(step.ui == false){
|
||||
// No UI
|
||||
}
|
||||
else if(options.inBrowser) {
|
||||
else if(step.inBrowser) {
|
||||
// Remove the DIV Element
|
||||
console.log("Removing Step \""+identity.stepName+"\" of \""+identity.imageName+"\".");
|
||||
console.log("Removing Step \""+step.name+"\" of \""+step.imageName+"\".");
|
||||
}
|
||||
else {
|
||||
// Delete the NodeJS Object
|
||||
console.log('\x1b[31m%s\x1b[0m',"Removing Step \""+identity.stepName+"\" of \""+identity.imageName+"\".");
|
||||
console.log('\x1b[31m%s\x1b[0m',"Removing Step \""+step.name+"\" of \""+step.imageName+"\".");
|
||||
}
|
||||
}
|
||||
|
||||
return UI;
|
||||
|
||||
}
|
||||
return events;
|
||||
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
module.exports = function CropModule(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Crop Image";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
require('./Crop')(input,options,function(out,format){
|
||||
@@ -29,7 +29,8 @@
|
||||
src: out,
|
||||
format: format
|
||||
}
|
||||
UI.onComplete(out);
|
||||
options.step.output = out;
|
||||
UI.onComplete(options.step);
|
||||
callback();
|
||||
});
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
module.exports = function DoNothing(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Decode QR Code";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
var jsQR = require('jsqr');
|
||||
var getPixels = require('get-pixels');
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
|
||||
const step = this;
|
||||
getPixels(input.src,function(err,pixels){
|
||||
@@ -22,13 +22,15 @@ module.exports = function DoNothing(options,UI) {
|
||||
step.output = input;
|
||||
step.output.data = decoded;
|
||||
callback();
|
||||
UI.onComplete(input.src);
|
||||
options.step.output = input.src;
|
||||
UI.onComplete(options.step);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
options: options,
|
||||
draw: draw,
|
||||
output: output
|
||||
output: output,
|
||||
UI: UI
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,17 @@
|
||||
module.exports = function DoNothing(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Do Nothing";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
|
||||
this.output = input;
|
||||
|
||||
options.step.output = this.output.src;
|
||||
callback();
|
||||
UI.onComplete(this.output.src);
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -5,12 +5,12 @@ module.exports = function DoNothingPix(options,UI) {
|
||||
|
||||
options = options || {};
|
||||
options.title = "Do Nothing with pixels";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -18,7 +18,8 @@ module.exports = function DoNothingPix(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype}
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
|
||||
@@ -6,12 +6,12 @@ module.exports = function GreenChannel(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Green channel only";
|
||||
options.description = "Displays only the green channel of an image";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -19,7 +19,8 @@ module.exports = function GreenChannel(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
|
||||
@@ -6,14 +6,14 @@ module.exports = function GreenChannel(options,UI) {
|
||||
options = options || {};
|
||||
options.title = "Invert Colors";
|
||||
options.description = "Inverts the colors of the image";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
//function setup() {} // optional
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -21,7 +21,8 @@ module.exports = function GreenChannel(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
|
||||
@@ -5,12 +5,12 @@ module.exports = function NdviRed(options,UI) {
|
||||
|
||||
options = options || {};
|
||||
options.title = "NDVI for red-filtered cameras (blue is infrared)";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -20,7 +20,8 @@ module.exports = function NdviRed(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
|
||||
@@ -2,12 +2,12 @@ module.exports = function SegmentedColormap(options,UI) {
|
||||
|
||||
options = options || {};
|
||||
options.title = "Segmented Colormap";
|
||||
UI.onSetup();
|
||||
UI.onSetup(options.step);
|
||||
var output;
|
||||
|
||||
function draw(input,callback) {
|
||||
|
||||
UI.onDraw();
|
||||
UI.onDraw(options.step);
|
||||
const step = this;
|
||||
|
||||
function changePixel(r, g, b, a) {
|
||||
@@ -18,7 +18,8 @@ module.exports = function SegmentedColormap(options,UI) {
|
||||
}
|
||||
function output(image,datauri,mimetype){
|
||||
step.output = {src:datauri,format:mimetype};
|
||||
UI.onComplete(datauri);
|
||||
options.step.output = datauri;
|
||||
UI.onComplete(options.step);
|
||||
}
|
||||
return require('../_nomodule/PixelManipulation.js')(input, {
|
||||
output: output,
|
||||
|
||||
@@ -43,7 +43,7 @@ module.exports = function PixelManipulation(image, options) {
|
||||
// but node modules and their documentation are essentially arcane on this point
|
||||
var chunks = [];
|
||||
var totalLength = 0;
|
||||
var r = savePixels(pixels, options.format);
|
||||
var r = savePixels(pixels, options.format, {quality: 100});
|
||||
|
||||
r.on('data', function(chunk){
|
||||
totalLength += chunk.length;
|
||||
|
||||
@@ -17,15 +17,19 @@ test('loadImages/loadImage has a name generator.', function (t){
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('loadImages/loadImage returns a wrapper.', function (t){
|
||||
var returnval = sequencer.loadImage(red);
|
||||
test('loadImages/loadImage returns a wrapper in the callback.', function (t){
|
||||
sequencer.loadImage(red, function() {
|
||||
var returnval = this;
|
||||
t.equal(returnval.name,"ImageSequencer Wrapper", "Wrapper is returned");
|
||||
t.equal(returnval.images[0],"image2","Image scope is defined");
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('addSteps is two-way chainable.', function (t){
|
||||
var returnval = sequencer.loadImage(red).addSteps('invert');
|
||||
sequencer.loadImage(red, function(){
|
||||
var returnval = this;
|
||||
this.addSteps('invert');
|
||||
t.equal(returnval.name,"ImageSequencer Wrapper", "Wrapper is returned");
|
||||
t.equal(returnval.images[0],"image3","Image scope is defined");
|
||||
t.equal(sequencer.images.image3.steps.length,2,"Loaded image is affected");
|
||||
@@ -33,6 +37,7 @@ test('addSteps is two-way chainable.', function (t){
|
||||
t.equal(sequencer.images.image2.steps.length,1,"Other images are not affected");
|
||||
t.equal(sequencer.images.image1.steps.length,1,"Other images are not affected");
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('addSteps is two-way chainable without loadImages.', function (t){
|
||||
@@ -44,11 +49,14 @@ test('addSteps is two-way chainable without loadImages.', function (t){
|
||||
});
|
||||
|
||||
test('removeSteps is two-way chainable.', function (t){
|
||||
var returnval = sequencer.loadImage(red).addSteps('invert').removeSteps(1);
|
||||
sequencer.loadImage(red,function(){
|
||||
var returnval = this;
|
||||
this.addSteps('invert').removeSteps(1);
|
||||
t.equal(returnval.name,"ImageSequencer Wrapper", "Wrapper is returned");
|
||||
t.equal(returnval.images[0],"image4","Image scope is defined");
|
||||
t.equal(sequencer.images.image4.steps.length,1);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('removeSteps is two-way chainable without loadImages.', function (t){
|
||||
@@ -59,12 +67,15 @@ test('removeSteps is two-way chainable without loadImages.', function (t){
|
||||
});
|
||||
|
||||
test('insertSteps is two-way chainable.', function (t){
|
||||
var returnval = sequencer.loadImage(red).insertSteps(1,'invert');
|
||||
sequencer.loadImage(red,function() {
|
||||
var returnval = this;
|
||||
this.insertSteps(1,'invert');
|
||||
t.equal(returnval.name,"ImageSequencer Wrapper","Wrapper is returned");
|
||||
t.equal(returnval.images[0],"image5","Image scope is defined");
|
||||
t.equal(sequencer.images.image5.steps.length,2);
|
||||
t.equal(sequencer.images.image5.steps[1].options.name,"invert","Correct Step Inserrted");
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('insertSteps is two-way chainable without loadImages.', function (t){
|
||||
|
||||
@@ -7,13 +7,21 @@ var test = require('tape');
|
||||
|
||||
require('../src/ImageSequencer.js');
|
||||
|
||||
//require image files as DataURLs so they can be tested alike on browser and Node.
|
||||
var sequencer = ImageSequencer({ ui: false });
|
||||
var image = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAQABADASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAf/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAABgj/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABykX//Z";
|
||||
var qr = require('../examples/IS-QR.js');
|
||||
sequencer.loadImages(image);
|
||||
|
||||
var qr = require('../examples/IS-QR.js');
|
||||
var test_png = require('../examples/test.png.js');
|
||||
var test_gif = require('../examples/test.gif.js');
|
||||
|
||||
sequencer.loadImages(test_png);
|
||||
sequencer.addSteps(['do-nothing-pix','invert','invert']);
|
||||
sequencer.run();
|
||||
|
||||
test("Preload", function(t) {
|
||||
sequencer.run(function(){
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test("Inverted image isn't identical", function (t) {
|
||||
t.notEqual(sequencer.images.image1.steps[1].output.src, sequencer.images.image1.steps[2].output.src);
|
||||
@@ -26,12 +34,32 @@ test("Twice inverted image is identical to original image", function (t) {
|
||||
});
|
||||
|
||||
test("Decode QR module works properly :: setup", function (t) {
|
||||
sequencer.loadImage(qr).addSteps('decode-qr').run(function(){
|
||||
sequencer.loadImage(qr,function(){
|
||||
this.addSteps('decode-qr').run(function(){
|
||||
t.end();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
test("Decode QR module works properly :: teardown", function (t) {
|
||||
t.equal("http://github.com/publiclab/image-sequencer",sequencer.images.image2.steps[1].output.data);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test("PixelManipulation works for PNG images", function (t) {
|
||||
sequencer.loadImages(test_png,function(){
|
||||
this.addSteps('invert').run(function(out){
|
||||
t.equal(1,1)
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("PixelManipulation works for GIF images", function (t) {
|
||||
sequencer.loadImages(test_gif,function(){
|
||||
this.addSteps('invert').run(function(out){
|
||||
t.equal(1,1)
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,18 +40,22 @@ test('loadImages loads a DataURL image and creates a step.', function (t){
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('loadImages loads a PATH image and creates a step. (NodeJS)', function (t){
|
||||
if(sequencer.options.inBrowser){
|
||||
t.equal("not applicable","not applicable","Not applicable for Browser");
|
||||
if(!sequencer.options.inBrowser)
|
||||
test('loadImage loads an image from URL and creates a step. (NodeJS)', function (t){
|
||||
sequencer.loadImage('URL','https://ccpandhare.github.io/image-sequencer/examples/red.jpg', function(){
|
||||
t.equal(sequencer.images.URL.steps.length, 1, "Initial Step Created");
|
||||
t.equal(typeof(sequencer.images.URL.steps[0].output.src), "string", "Initial output exists");
|
||||
t.end();
|
||||
}
|
||||
else {
|
||||
sequencer.loadImages(red);
|
||||
});
|
||||
});
|
||||
|
||||
if(!sequencer.options.inBrowser)
|
||||
test('loadImages loads an image from PATH and creates a step. (NodeJS)', function (t){
|
||||
sequencer.loadImages('examples/red.jpg');
|
||||
t.equal(sequencer.images.image1.steps.length, 1, "Initial Step Created");
|
||||
t.equal(typeof(sequencer.images.image1.steps[0].output.src), "string", "Initial output exists");
|
||||
t.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('loadImage works too.', function (t){
|
||||
sequencer.loadImage('test2',red);
|
||||
|
||||
Reference in New Issue
Block a user