├── .DS_Store
├── .babelrc
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── ChangeLogs.md
├── LICENSE
├── README.md
├── addon
├── codemirror-colorpicker.css
├── codemirror-colorpicker.js
├── colorpicker
│ ├── colorpicker.css
│ ├── colorpicker.js
│ └── colorview.js
└── sample
│ └── colorpicker.html
├── config
├── rollup.config.dev.js
└── rollup.config.prod.js
├── dist
├── codemirror-colorpicker.css
├── codemirror-colorpicker.js
└── codemirror-colorpicker.min.js
├── gl.html
├── index.html
├── package.json
├── resources
└── image
│ ├── colorpaletts.png
│ ├── colorpicker.png
│ ├── grapes.jpg
│ ├── palette-type.png
│ ├── scalecolors-title.png
│ ├── scalecolors.png
│ ├── screen-shot.png
│ └── sketch-type.png
├── src
├── colorpicker
│ ├── BaseBox.js
│ ├── BaseColorPicker.js
│ ├── BaseModule.js
│ ├── BaseSlider.js
│ ├── BaseStore.js
│ ├── UIElement.js
│ ├── VerticalSlider.js
│ ├── box
│ │ ├── ColorControl.js
│ │ └── index.js
│ ├── chromedevtool
│ │ ├── ColorControl.js
│ │ └── index.js
│ ├── index.js
│ ├── macos
│ │ ├── ColorControl.js
│ │ └── index.js
│ ├── mini-vertical
│ │ ├── ColorControl.js
│ │ └── index.js
│ ├── mini
│ │ ├── ColorControl.js
│ │ └── index.js
│ ├── module
│ │ ├── ColorManager.js
│ │ └── ColorSetsList.js
│ ├── ring
│ │ ├── ColorControl.js
│ │ └── index.js
│ ├── ui
│ │ ├── ColorInformation.js
│ │ ├── ColorPalette.js
│ │ ├── ColorRing.js
│ │ ├── ColorSetsChooser.js
│ │ ├── ColorWheel.js
│ │ ├── CurrentColorSets.js
│ │ ├── CurrentColorSetsContextMenu.js
│ │ ├── Eyedropper.js
│ │ ├── Eyedropper.scss
│ │ └── control
│ │ │ ├── Hue.js
│ │ │ ├── Opacity.js
│ │ │ ├── Value.js
│ │ │ ├── VerticalHue.js
│ │ │ └── VerticalOpacity.js
│ ├── vscode
│ │ ├── ColorControl.js
│ │ └── index.js
│ └── xd
│ │ ├── ColorControl.js
│ │ └── index.js
├── extension
│ └── codemirror
│ │ ├── colorview.js
│ │ └── index.js
├── index.js
├── scss
│ ├── colorpicker.scss
│ ├── colorview.scss
│ ├── component
│ │ ├── button.scss
│ │ ├── colorchooser.scss
│ │ ├── colorsets-contextmenu.scss
│ │ ├── colorsets.scss
│ │ ├── control.scss
│ │ ├── gradient-editor.scss
│ │ ├── gradient-picker.scss
│ │ ├── information.scss
│ │ └── palette.scss
│ ├── index.scss
│ ├── mixins.scss
│ └── themes
│ │ ├── box.scss
│ │ ├── macos.scss
│ │ ├── mini-vertical.scss
│ │ ├── mini.scss
│ │ ├── palette.scss
│ │ ├── ring.scss
│ │ ├── sketch.scss
│ │ ├── vscode.scss
│ │ └── xd.scss
└── util
│ ├── Blender.js
│ ├── Canvas.js
│ ├── Color.js
│ ├── ColorNames.js
│ ├── Dom.js
│ ├── Event.js
│ ├── EventMachin.js
│ ├── GL.js
│ ├── HueColor.js
│ ├── ImageFilter.js
│ ├── ImageLoader.js
│ ├── Kmeans.js
│ ├── Matrix.js
│ ├── State.js
│ ├── blend
│ ├── composite.js
│ ├── non-separable.js
│ └── separable.js
│ ├── filter
│ ├── StackBlur.js
│ ├── functions.js
│ ├── image
│ │ ├── crop.js
│ │ ├── flipH.js
│ │ ├── flipV.js
│ │ ├── histogram.js
│ │ ├── index.js
│ │ ├── resize.js
│ │ ├── rotate.js
│ │ └── rotateDegree.js
│ ├── index.js
│ ├── matrix
│ │ ├── blur.js
│ │ ├── emboss.js
│ │ ├── gaussian-blur-5x.js
│ │ ├── gaussian-blur.js
│ │ ├── grayscale2.js
│ │ ├── index.js
│ │ ├── kirsch-horizontal.js
│ │ ├── kirsch-vertical.js
│ │ ├── laplacian-5x.js
│ │ ├── laplacian.js
│ │ ├── motion-blur-2.js
│ │ ├── motion-blur-3.js
│ │ ├── motion-blur.js
│ │ ├── negative.js
│ │ ├── normal.js
│ │ ├── sepia2.js
│ │ ├── sharpen.js
│ │ ├── sobel-horizontal.js
│ │ ├── sobel-vertical.js
│ │ ├── stack-blur.js
│ │ ├── transparency.js
│ │ └── unsharp-masking.js
│ ├── multi
│ │ ├── index.js
│ │ ├── kirsch.js
│ │ ├── sobel.js
│ │ └── vintage.js
│ └── pixel
│ │ ├── bitonal.js
│ │ ├── brightness.js
│ │ ├── brownie.js
│ │ ├── clip.js
│ │ ├── contrast.js
│ │ ├── gamma.js
│ │ ├── gradient.js
│ │ ├── grayscale.js
│ │ ├── hue.js
│ │ ├── index.js
│ │ ├── invert.js
│ │ ├── kodachrome.js
│ │ ├── matrix.js
│ │ ├── noise.js
│ │ ├── opacity.js
│ │ ├── polaroid.js
│ │ ├── saturation.js
│ │ ├── sepia.js
│ │ ├── shade.js
│ │ ├── shift.js
│ │ ├── solarize.js
│ │ ├── technicolor.js
│ │ ├── threshold-color.js
│ │ ├── threshold.js
│ │ └── tint.js
│ ├── functions
│ ├── formatter.js
│ ├── fromCMYK.js
│ ├── fromHSL.js
│ ├── fromHSV.js
│ ├── fromLAB.js
│ ├── fromRGB.js
│ ├── fromYCrCb.js
│ ├── func.js
│ ├── image.js
│ ├── math.js
│ ├── mixin.js
│ ├── parser.js
│ └── support.js
│ ├── gl
│ ├── filter
│ │ ├── index.js
│ │ ├── matrix
│ │ │ ├── blur.js
│ │ │ ├── emboss.js
│ │ │ ├── gaussian-blur-5x.js
│ │ │ ├── gaussian-blur.js
│ │ │ ├── grayscale2.js
│ │ │ ├── index.js
│ │ │ ├── kirsch-horizontal.js
│ │ │ ├── kirsch-vertical.js
│ │ │ ├── laplacian-5x.js
│ │ │ ├── laplacian.js
│ │ │ ├── motion-blur-2.js
│ │ │ ├── motion-blur-3.js
│ │ │ ├── motion-blur.js
│ │ │ ├── negative.js
│ │ │ ├── normal.js
│ │ │ ├── sepia2.js
│ │ │ ├── sharpen.js
│ │ │ ├── sobel-horizontal.js
│ │ │ ├── sobel-vertical.js
│ │ │ ├── transparency.js
│ │ │ └── unsharp-masking.js
│ │ ├── multi
│ │ │ ├── index.js
│ │ │ ├── kirsch.js
│ │ │ ├── sobel.js
│ │ │ └── vintage.js
│ │ ├── pixel
│ │ │ ├── bitonal.js
│ │ │ ├── brightness.js
│ │ │ ├── brownie.js
│ │ │ ├── chaos.js
│ │ │ ├── clip.js
│ │ │ ├── contrast.js
│ │ │ ├── gamma.js
│ │ │ ├── gradient.js
│ │ │ ├── grayscale.js
│ │ │ ├── hue.js
│ │ │ ├── index.js
│ │ │ ├── invert.js
│ │ │ ├── kodachrome.js
│ │ │ ├── matrix.js
│ │ │ ├── noise.js
│ │ │ ├── opacity.js
│ │ │ ├── polaroid.js
│ │ │ ├── saturation.js
│ │ │ ├── sepia.js
│ │ │ ├── shade.js
│ │ │ ├── shift.js
│ │ │ ├── solarize.js
│ │ │ ├── technicolor.js
│ │ │ ├── threshold-color.js
│ │ │ ├── threshold.js
│ │ │ └── tint.js
│ │ └── util.js
│ ├── functions.js
│ └── index.js
│ └── index.js
├── stand.html
└── test
├── util.Blend.spec.js
├── util.Color.spec.js
├── util.Filter.spec.js
└── util.ImageFilter.spec.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/.DS_Store
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "test": {
4 | "presets" : [ ["env"] ],
5 | "plugins": [
6 | "transform-es2015-modules-commonjs",
7 | "transform-object-rest-spread"
8 | ]
9 | },
10 | "development" : {
11 | "presets" : [
12 | [ "env", {"modules" : false } ]
13 | ],
14 | "plugins": [
15 | "external-helpers",
16 | "transform-object-rest-spread"
17 | ]
18 | },
19 | "production" : {
20 | "presets" : [
21 | [ "env", {"modules" : false } ]
22 | ],
23 | "plugins": [
24 | "external-helpers",
25 | "transform-object-rest-spread"
26 | ]
27 | }
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Browser [e.g. chrome, safari]
26 | - Version [e.g. 22]
27 |
28 | **Smartphone (please complete the following information):**
29 | - Device: [e.g. iPhone6]
30 | - OS: [e.g. iOS8.1]
31 | - Browser [e.g. stock browser, safari]
32 | - Version [e.g. 22]
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .DS_Store
3 | test-report/
4 | package-lock.json
--------------------------------------------------------------------------------
/ChangeLogs.md:
--------------------------------------------------------------------------------
1 |
2 | # Change Logs
3 |
4 | # 1.6.5
5 | * image filter (gray)
6 | * support lab color (RGBtoLAB, LABtoRGB)
7 |
8 | # 1.6.4
9 | * improved performance of color palette for image
10 | * support only palette style
11 |
12 | ## 1.6.3
13 | * Support Sketch Style
14 | * support color palette for image
15 | * support parsing for number color code (ex: 0xffffff -> {hex, r, g, b, a})
16 |
17 | ## v1.6.0
18 | * support color scale
19 |
20 | ## v1.5.0
21 | * change bundler - rollup based
22 | * support color palettes
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 jinho park (cyberuls@gmail.com, easylogic)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/config/rollup.config.dev.js:
--------------------------------------------------------------------------------
1 | import packageJSON from '../package.json'
2 | import postcss from 'rollup-plugin-postcss'
3 | import babel from 'rollup-plugin-babel';
4 | import serve from 'rollup-plugin-serve'
5 | import livereload from 'rollup-plugin-livereload'
6 | import autoprefixer from 'autoprefixer'
7 | import glslify from 'rollup-plugin-glslify';
8 | import peerDepsExternal from 'rollup-plugin-peer-deps-external';
9 |
10 | // rollup.config.js
11 | export default {
12 | input: 'src/index.js',
13 | output: {
14 | file: 'addon/' + packageJSON.name + '.js',
15 | format: 'iife',
16 | globals: {
17 | "codemirror" : "window.CodeMirror"
18 | },
19 | external: ['codemirror']
20 | },
21 | name: 'CodeMirrorColorPicker',
22 | plugins : [
23 | peerDepsExternal(),
24 | serve(),
25 | livereload({watch: 'addon'}),
26 | glslify({ basedir: 'src/util/glsl/source' }),
27 | //scss({output : 'addon/' + packageJSON.name + '.css'}),
28 | postcss({
29 | extract: 'addon/' + packageJSON.name + '.css',
30 | plugins: [
31 | autoprefixer()
32 | ],
33 | extensions: ['.scss']
34 | }),
35 | babel({
36 | exclude: ['node_modules/**', 'src/util/glsl/source/**'],
37 | presets: [
38 | [ 'es2015', { modules : false } ]
39 | ]
40 | })
41 | ],
42 | watch: {
43 | chokidar: {
44 | // if the chokidar option is given, rollup-watch will
45 | // use it instead of fs.watch. You will need to install
46 | // chokidar separately.
47 | //
48 | // this options object is passed to chokidar. if you
49 | // don't have any options, just pass `chokidar: true`
50 | },
51 |
52 | // include and exclude govern which files to watch. by
53 | // default, all dependencies will be watched
54 | exclude: ['node_modules/**']
55 | }
56 | };
--------------------------------------------------------------------------------
/config/rollup.config.prod.js:
--------------------------------------------------------------------------------
1 | import packageJSON from '../package.json'
2 | import postcss from 'rollup-plugin-postcss'
3 | import babel from 'rollup-plugin-babel';
4 | import uglify from 'rollup-plugin-uglify';
5 | import autoprefixer from 'autoprefixer'
6 | import glslify from 'rollup-plugin-glslify';
7 | import peerDepsExternal from 'rollup-plugin-peer-deps-external';
8 |
9 |
10 | // rollup.config.js
11 | export default [{
12 | input: 'src/index.js',
13 | output: {
14 | file: 'dist/' + packageJSON.name + '.min.js',
15 | format: 'iife',
16 | globals: {
17 | "codemirror" : "window.CodeMirror"
18 | },
19 | external: ['codemirror']
20 | },
21 | name: 'CodeMirrorColorPicker',
22 | plugins : [
23 | peerDepsExternal(),
24 | glslify({ basedir: 'src/util/glsl/source' }),
25 | //scss({output : 'dist/' + packageJSON.name + '.css'}),
26 | postcss({
27 | extract: 'dist/' + packageJSON.name + '.css',
28 | plugins: [
29 | autoprefixer()
30 | ],
31 | extensions: ['.scss']
32 | }),
33 | babel({
34 | exclude: ['node_modules/**', 'src/util/glsl/source/**']
35 | }),
36 | uglify()
37 | ]
38 | }, {
39 | input: 'src/index.js',
40 | output: {
41 | file: 'dist/' + packageJSON.name + '.js',
42 | format: 'umd',
43 | globals: {
44 | "codemirror" : "CodeMirror"
45 | },
46 | external: ['codemirror']
47 | },
48 | name: 'codemirror-colorpicker',
49 | plugins : [
50 | postcss({
51 | extract: 'dist/' + packageJSON.name + '.css',
52 | plugins: [
53 | autoprefixer()
54 | ],
55 | extensions: ['.scss']
56 | }),
57 | babel({
58 | exclude: 'node_modules/**'
59 | })
60 | ]
61 | }];
--------------------------------------------------------------------------------
/gl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codemirror-colorpicker",
3 | "version": "1.9.80",
4 | "description": "simple colorpicker used anywhere",
5 | "main": "./dist/codemirror-colorpicker.js",
6 | "scripts": {
7 | "pub": "npm run build && npm publish",
8 | "build": "NODE_ENV=production rollup --config config/rollup.config.prod.js",
9 | "dev": "NODE_ENV=development rollup -w --config config/rollup.config.dev.js",
10 | "docs": "http-server ./docs",
11 | "test": "NODE_ENV=test jest --watch"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/easylogic/codemirror-colorpicker.git"
16 | },
17 | "keywords": [
18 | "codemirror",
19 | "colorview",
20 | "colorpicker",
21 | "imagefilter",
22 | "color",
23 | "rgb",
24 | "webgl",
25 | "chromdevtool",
26 | "macos",
27 | "sketch",
28 | "palette"
29 | ],
30 | "author": "easylogic",
31 | "license": "MIT",
32 | "bugs": {
33 | "url": "https://github.com/easylogic/codemirror-colorpicker/issues"
34 | },
35 | "homepage": "https://colorpicker.easylogic.studio/",
36 | "devDependencies": {
37 | "autoprefixer": "^7.2.5",
38 | "babel-cli": "^6.26.0",
39 | "babel-core": "^6.26.0",
40 | "babel-jest": "^22.4.1",
41 | "babel-plugin-external-helpers": "^6.22.0",
42 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
43 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
44 | "babel-preset-env": "^1.6.1",
45 | "babel-preset-es2015": "^6.24.1",
46 | "babel-preset-es2015-rollup": "^3.0.0",
47 | "babel-preset-minify": "^0.2.0",
48 | "codemirror": "^5.48.0",
49 | "cross-env": "^5.1.1",
50 | "http-server": "^0.11.1",
51 | "jest": "^22.4.2",
52 | "jest-cli": "^22.4.2",
53 | "jest-report": "^0.1.11",
54 | "rollup": "^0.52.1",
55 | "rollup-plugin-babel": "^3.0.3",
56 | "rollup-plugin-css-only": "^0.2.0",
57 | "rollup-plugin-glslify": "^1.0.5",
58 | "rollup-plugin-json": "^2.3.0",
59 | "rollup-plugin-livereload": "^0.6.0",
60 | "rollup-plugin-minify": "^1.0.3",
61 | "rollup-plugin-peer-deps-external": "^2.2.0",
62 | "rollup-plugin-postcss": "^1.2.7",
63 | "rollup-plugin-scss": "^0.4.0",
64 | "rollup-plugin-serve": "^0.4.2",
65 | "rollup-plugin-uglify": "^2.0.1",
66 | "rollup-watch": "^4.3.1",
67 | "uglify-es": "^3.2.2"
68 | },
69 | "peerDependencies": {
70 | "codemirror": "^5.48.0"
71 | },
72 | "dependencies": {},
73 | "jest": {
74 | "modulePaths": [
75 | "/src",
76 | "/node_modules"
77 | ],
78 | "globals": {
79 | "NODE_ENV": "test"
80 | },
81 | "verbose": false,
82 | "moduleFileExtensions": [
83 | "js",
84 | "json"
85 | ],
86 | "testRegex": "test/.*\\.spec\\.js$",
87 | "testEnvironment": "node"
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/resources/image/colorpaletts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/colorpaletts.png
--------------------------------------------------------------------------------
/resources/image/colorpicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/colorpicker.png
--------------------------------------------------------------------------------
/resources/image/grapes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/grapes.jpg
--------------------------------------------------------------------------------
/resources/image/palette-type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/palette-type.png
--------------------------------------------------------------------------------
/resources/image/scalecolors-title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/scalecolors-title.png
--------------------------------------------------------------------------------
/resources/image/scalecolors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/scalecolors.png
--------------------------------------------------------------------------------
/resources/image/screen-shot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/screen-shot.png
--------------------------------------------------------------------------------
/resources/image/sketch-type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kode-team/codemirror-colorpicker/f73b1638be8dad4b9d9b2ea7521308b7e136ee53/resources/image/sketch-type.png
--------------------------------------------------------------------------------
/src/colorpicker/BaseBox.js:
--------------------------------------------------------------------------------
1 |
2 | import Event from '../util/Event'
3 | import UIElement from './UIElement';
4 |
5 | export default class BaseBox extends UIElement {
6 |
7 | constructor (opt) {
8 | super(opt)
9 |
10 | this.source = 'base-box'
11 | }
12 |
13 |
14 | refresh () {
15 |
16 | }
17 |
18 | refreshColorUI (e) {
19 |
20 | }
21 |
22 | /** push change event */
23 | changeColor (opt) {
24 | this.$store.dispatch('/changeColor',Object.assign({
25 | source: this.source
26 | }, opt || {}))
27 | }
28 |
29 | // Event Bindings
30 | 'mouseup document' (e) {
31 | this.onDragEnd(e);
32 | }
33 |
34 | 'mousemove document' (e) {
35 | this.onDragMove(e);
36 | }
37 |
38 | 'mousedown $bar' (e) {
39 | e.preventDefault();
40 | this.isDown = true;
41 | }
42 |
43 | 'mousedown $container' (e) {
44 | this.isDown = true
45 | this.onDragStart(e);
46 | }
47 |
48 | 'touchend document' (e) {
49 | this.onDragEnd(e);
50 | }
51 |
52 | 'touchmove document' (e) {
53 | this.onDragMove(e);
54 | }
55 |
56 | 'touchstart $bar' (e) {
57 | e.preventDefault();
58 | this.isDown = true;
59 | }
60 |
61 | 'touchstart $container' (e) {
62 | this.onDragStart(e);
63 | }
64 |
65 |
66 | onDragStart (e) {
67 | this.isDown = true;
68 | this.refreshColorUI(e);
69 | }
70 |
71 | onDragMove (e) {
72 | if (this.isDown) {
73 | this.refreshColorUI(e);
74 | }
75 | }
76 |
77 | /* called when mouse is ended move */
78 | onDragEnd (e) {
79 | if (this.isDown) {
80 | this.$store.emit('lastUpdateColor');
81 | this.isDown = false
82 | }
83 | }
84 |
85 |
86 | '@changeColor' (sourceType) {
87 | if (this.source != sourceType) {
88 | this.refresh()
89 | }
90 | }
91 |
92 | '@initColor' () { this.refresh() }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/colorpicker/BaseModule.js:
--------------------------------------------------------------------------------
1 | export default class BaseModule {
2 | constructor ($store) {
3 | this.$store = $store;
4 | this.initialize();
5 | }
6 |
7 | initialize() {
8 | this.filterProps().forEach(key => {
9 | this.$store.action(key, this);
10 | });
11 | }
12 |
13 | filterProps (pattern = '/') {
14 | return Object.getOwnPropertyNames(this.__proto__).filter(key => {
15 | return key.startsWith(pattern);
16 | });
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/src/colorpicker/BaseSlider.js:
--------------------------------------------------------------------------------
1 |
2 | import Event from '../util/Event'
3 | import BaseBox from './BaseBox';
4 |
5 | export default class BaseSlider extends BaseBox {
6 |
7 | constructor (opt) {
8 | super(opt)
9 |
10 | this.minValue = 0 // min domain value
11 | this.maxValue = 1 // max domain value
12 | this.source = 'base-slider'
13 | }
14 |
15 | /* slider container's min and max position */
16 | getMinMaxPosition () {
17 | var min = this.getMinPosition();
18 | var width = this.getMaxDist()
19 | var max = min + width;
20 |
21 | return { min, max, width }
22 | }
23 |
24 | /** get current position on page */
25 | getCurrent (value) {
26 | return min + this.getMaxDist() * value;
27 | }
28 |
29 | /** get min position on slider container */
30 | getMinPosition () {
31 | return this.refs.$container.offset().left;
32 | }
33 |
34 | getMaxDist () {
35 | return this.state.get('$container.width');
36 | }
37 |
38 | /** get dist for position value */
39 | getDist (current) {
40 | var {min, max} = this.getMinMaxPosition()
41 |
42 | var dist;
43 | if (current < min) {
44 | dist = 0;
45 | } else if (current > max) {
46 | dist = 100;
47 | } else {
48 | dist = (current - min) / (max - min) * 100;
49 | }
50 |
51 | return dist;
52 | }
53 |
54 | /** get caculated dist for domain value */
55 | getCaculatedDist (e) {
56 | var current = e ? this.getMousePosition(e) : this.getCurrent(this.getDefaultValue() / this.maxValue);
57 | var dist = this.getDist(current);
58 |
59 | return dist;
60 | }
61 |
62 | /** get default value used in slider container */
63 | getDefaultValue () {
64 | return 0
65 | }
66 |
67 | /** set mosue position */
68 | setMousePosition (x) {
69 | this.refs.$bar.css({ left : (x) + 'px' });
70 | }
71 |
72 | /** set mouse position in page */
73 | getMousePosition (e) {
74 | return Event.pos(e).pageX;
75 | }
76 |
77 | refresh () {
78 | this.setColorUI()
79 | }
80 |
81 | /** set drag bar position */
82 | setColorUI(v) {
83 |
84 | v = v || this.getDefaultValue();
85 |
86 | if (v <= this.minValue) {
87 | this.refs.$bar.addClass('first').removeClass('last')
88 | } else if (v >= this.maxValue) {
89 | this.refs.$bar.addClass('last').removeClass('first')
90 | } else {
91 | this.refs.$bar.removeClass('last').removeClass('first')
92 | }
93 |
94 | this.setMousePosition(this.getMaxDist() * ( (v || 0) / this.maxValue));
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/src/colorpicker/BaseStore.js:
--------------------------------------------------------------------------------
1 | export default class BaseStore {
2 | constructor (opt) {
3 | this.callbacks = []
4 | this.actions = []
5 | this.modules = opt.modules || []
6 |
7 | this.initialize()
8 | }
9 |
10 | initialize () {
11 | this.initializeModule();
12 | }
13 |
14 | initializeModule () {
15 | this.modules.forEach(Module => {
16 | var instance = new Module(this);
17 | })
18 | }
19 |
20 | action (action, context) {
21 | this.actions[action] = { context, callback: context[action] };
22 | }
23 |
24 | dispatch (action) {
25 | var args = [...arguments];
26 | var action = args.shift();
27 |
28 | var m = this.actions[action];
29 |
30 | if (m) {
31 | return m.callback.apply(m.context, [this, ...args]);
32 | }
33 | }
34 |
35 | module (ModuleObject) {
36 | // this.action()
37 | }
38 |
39 | on (event, callback) {
40 | this.callbacks.push({ event, callback })
41 | }
42 |
43 | off (event, callback) {
44 |
45 | if (arguments.length == 0) {
46 | this.callbacks = []
47 | } else if (arguments.length == 1) {
48 | this.callbacks = this.callbacks.filter(f => {
49 | return f.event != event
50 | })
51 | } else if (arguments.length == 2) {
52 | this.callbacks = this.callbacks.filter(f => {
53 | return f.event != event && f.callback != callback
54 | })
55 | }
56 |
57 | }
58 |
59 | emit () {
60 | var args = [...arguments];
61 | var event = args.shift();
62 |
63 | this.callbacks.filter(f => {
64 | return (f.event == event)
65 | }).forEach(f => {
66 | if (f && typeof f.callback == 'function') {
67 | f.callback(...args);
68 | }
69 | })
70 | }
71 | }
--------------------------------------------------------------------------------
/src/colorpicker/UIElement.js:
--------------------------------------------------------------------------------
1 | import EventMachin from "../util/EventMachin";
2 |
3 | const CHECK_STORE_EVENT_PATTERN = /^@/
4 |
5 | class UIElement extends EventMachin {
6 | constructor (opt) {
7 | super(opt)
8 |
9 | this.opt = opt || {};
10 |
11 | if (opt && opt.$store) {
12 | this.$store = opt.$store
13 | }
14 |
15 | this.initialize();
16 |
17 | this.initializeStoreEvent();
18 | }
19 |
20 | /**
21 | * initialize store event
22 | *
23 | * you can define '@xxx' method(event) in UIElement
24 | *
25 | *
26 | */
27 | initializeStoreEvent () {
28 | this.storeEvents = {}
29 | this.filterProps(CHECK_STORE_EVENT_PATTERN).forEach((key) => {
30 | const arr = key.split('@')
31 | arr.shift();
32 | const event = arr.join('@');
33 |
34 | this.storeEvents[event] = this[key].bind(this)
35 | this.$store.on(event, this.storeEvents[event]);
36 | });
37 | }
38 |
39 | destoryStoreEvent () {
40 | Object.keys(this.storeEvents).forEach(event => {
41 | this.$store.off(event, this.storeEvents[event])
42 | })
43 | }
44 | }
45 |
46 | export default UIElement
--------------------------------------------------------------------------------
/src/colorpicker/VerticalSlider.js:
--------------------------------------------------------------------------------
1 | import Event from '../util/Event'
2 | import BaseSlider from "./BaseSlider";
3 |
4 | export default class VerticalSlider extends BaseSlider {
5 |
6 | constructor (opt) {
7 | super(opt)
8 |
9 | this.source = 'vertical-slider'
10 | }
11 |
12 | /** get max height for vertical slider */
13 | getMaxDist () {
14 | return this.state.get('$container.height');
15 | }
16 |
17 | /** set mouse pointer for vertical slider */
18 | setMousePosition (y) {
19 | this.refs.$bar.css({ top : (y) + 'px' });
20 | }
21 |
22 | /** get mouse position by pageY for vertical slider */
23 | getMousePosition (e) {
24 | return Event.pos(e).pageY;
25 | }
26 |
27 | /** get min position for vertial slider */
28 | getMinPosition () {
29 | return this.refs.$container.offset().top;
30 | }
31 |
32 | /** get caculated dist for domain value */
33 | getCaculatedDist (e) {
34 | var current = e ? this.getMousePosition(e) : this.getCurrent(this.getDefaultValue() / this.maxValue);
35 | var dist = 100 - this.getDist(current);
36 |
37 | return dist;
38 | }
39 |
40 | /** set drag bar position */
41 | setColorUI(v) {
42 |
43 | v = v || this.getDefaultValue();
44 |
45 | if (v <= this.minValue) {
46 | this.refs.$bar.addClass('first').removeClass('last')
47 | } else if (v >= this.maxValue) {
48 | this.refs.$bar.addClass('last').removeClass('first')
49 | } else {
50 | this.refs.$bar.removeClass('last').removeClass('first')
51 | }
52 |
53 | var per = 1 - ( (v || 0) / this.maxValue);
54 |
55 | this.setMousePosition(this.getMaxDist() * per );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/colorpicker/box/ColorControl.js:
--------------------------------------------------------------------------------
1 | import { enableEyeDropper } from '../../util/functions/support';
2 | import Hue from '../ui/control/Hue';
3 | import Opacity from '../ui/control/Opacity'
4 | import UIElement from '../UIElement';
5 | import Eyedropper from '../ui/Eyedropper';
6 |
7 | const source = 'chromedevtool-control';
8 |
9 | export default class ColorControl extends UIElement {
10 |
11 | components () {
12 | return { Hue, Opacity, Eyedropper }
13 | }
14 |
15 | template () {
16 |
17 | const hasEyeDropper = enableEyeDropper ? 'has-eyedropper' : '';
18 | let $eyedropper = !!enableEyeDropper ? `
19 |
22 | ` : '';
23 |
24 | return `
25 |
26 |
27 | ${$eyedropper}
28 |
32 |
33 |
34 |
35 |
36 |
37 | `
38 | }
39 |
40 | setBackgroundColor () {
41 | this.refs.$controlColor.css("background-color", this.$store.dispatch('/toRGB'));
42 | }
43 |
44 | refresh () {
45 | this.setColorUI();
46 | this.setBackgroundColor()
47 | }
48 |
49 | setColorUI() {
50 | this.Hue.setColorUI()
51 | this.Opacity.setColorUI()
52 | }
53 |
54 | '@changeColor' (sourceType) {
55 | if (source != sourceType) {
56 | this.refresh()
57 | }
58 | }
59 |
60 | '@initColor' () { this.refresh() }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/colorpicker/box/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 | import ColorInformation from '../ui/ColorInformation'
5 | import ColorPalette from '../ui/ColorPalette'
6 | import ColorSetsChooser from '../ui/ColorSetsChooser'
7 | import CurrentColorSets from '../ui/CurrentColorSets'
8 | import CurrentColorSetsContextMenu from '../ui/CurrentColorSetsContextMenu'
9 |
10 | export default class BoxColorPicker extends BaseColorPicker {
11 |
12 | template () {
13 | return /*html*/`
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | `
25 | }
26 |
27 | components() {
28 | return {
29 | palette: ColorPalette,
30 | control: ColorControl,
31 | information: ColorInformation,
32 | currentColorSets: CurrentColorSets,
33 | colorSetsChooser: ColorSetsChooser,
34 | contextMenu: CurrentColorSetsContextMenu
35 | }
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/src/colorpicker/chromedevtool/ColorControl.js:
--------------------------------------------------------------------------------
1 | import { enableEyeDropper } from '../../util/functions/support';
2 | import Hue from '../ui/control/Hue';
3 | import Opacity from '../ui/control/Opacity'
4 | import UIElement from '../UIElement';
5 | import Eyedropper from '../ui/Eyedropper';
6 |
7 | const source = 'chromedevtool-control';
8 |
9 | export default class ColorControl extends UIElement {
10 |
11 | components () {
12 | return { Hue, Opacity, Eyedropper }
13 | }
14 |
15 | template () {
16 |
17 | const hasEyeDropper = enableEyeDropper ? 'has-eyedropper' : '';
18 | let $eyedropper = !!enableEyeDropper ? `
19 |
22 | ` : '';
23 |
24 | return `
25 |
26 |
27 |
28 |
29 |
30 | ${$eyedropper}
31 |
32 | `
33 | }
34 |
35 | setBackgroundColor () {
36 | this.refs.$controlColor.css("background-color", this.$store.dispatch('/toRGB'));
37 | }
38 |
39 | refresh () {
40 | this.setColorUI();
41 | this.setBackgroundColor()
42 | }
43 |
44 | setColorUI() {
45 | this.Hue.setColorUI()
46 | this.Opacity.setColorUI()
47 | }
48 |
49 | '@changeColor' (sourceType) {
50 | if (source != sourceType) {
51 | this.refresh()
52 | }
53 | }
54 |
55 | '@initColor' () { this.refresh() }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/colorpicker/chromedevtool/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 | import ColorInformation from '../ui/ColorInformation'
5 | import ColorPalette from '../ui/ColorPalette'
6 | import ColorSetsChooser from '../ui/ColorSetsChooser'
7 | import CurrentColorSets from '../ui/CurrentColorSets'
8 | import CurrentColorSetsContextMenu from '../ui/CurrentColorSetsContextMenu'
9 |
10 | export default class ChromeDevToolColorPicker extends BaseColorPicker {
11 |
12 | template () {
13 | return `
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | `
23 | }
24 |
25 | components() {
26 | return {
27 | palette: ColorPalette,
28 | control: ColorControl,
29 | information: ColorInformation,
30 | currentColorSets: CurrentColorSets,
31 | colorSetsChooser: ColorSetsChooser,
32 | contextMenu: CurrentColorSetsContextMenu
33 | }
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/src/colorpicker/index.js:
--------------------------------------------------------------------------------
1 | import MacOSColorPicker from './macos/index'
2 | import ChromeDevToolColorPicker from './chromedevtool/index'
3 | import MiniColorPicker from './mini/index'
4 | import MiniVerticalColorPicker from './mini-vertical/index'
5 | import RingColorPicker from './ring/index'
6 | import XDColorPicker from './xd/index'
7 | import VSCodePicker from './vscode/index'
8 | import BoxColorPicker from './box/index'
9 |
10 | export default {
11 | create (opts) {
12 | switch(opts.type) {
13 | case 'box':
14 | return new BoxColorPicker(opts);
15 | case 'macos':
16 | return new MacOSColorPicker(opts);
17 | case 'xd':
18 | return new XDColorPicker(opts);
19 | case 'ring':
20 | return new RingColorPicker(opts);
21 | case 'mini':
22 | return new MiniColorPicker(opts);
23 | case 'vscode':
24 | return new VSCodePicker(opts);
25 | case 'mini-vertical':
26 | return new MiniVerticalColorPicker(opts);
27 | case 'sketch':
28 | case 'palette':
29 | default:
30 | return new ChromeDevToolColorPicker(opts);
31 | }
32 | },
33 | ColorPicker: ChromeDevToolColorPicker,
34 | ChromeDevToolColorPicker,
35 | MacOSColorPicker,
36 | RingColorPicker,
37 | MiniColorPicker,
38 | VSCodePicker,
39 | MiniVerticalColorPicker
40 | }
--------------------------------------------------------------------------------
/src/colorpicker/macos/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Value from '../ui/control/Value';
2 | import UIElement from '../UIElement';
3 | import Opacity from '../ui/control/Opacity'
4 | import Eyedropper from '../ui/Eyedropper';
5 | import { enableEyeDropper } from '../../util/functions/support';
6 |
7 | const source = 'macos-control';
8 |
9 | export default class ColorControl extends UIElement {
10 |
11 | components () {
12 | return { Value, Opacity, Eyedropper }
13 | }
14 |
15 | template () {
16 |
17 | const hasEyeDropper = enableEyeDropper ? 'has-eyedropper' : '';
18 | let $eyedropper = !!enableEyeDropper ? `
19 |
22 | ` : '';
23 |
24 |
25 | return `
26 |
27 |
28 |
29 |
30 |
31 | ${$eyedropper}
32 |
33 | `
34 | }
35 |
36 | setBackgroundColor () {
37 | this.refs.$controlColor.css("background-color", this.$store.dispatch('/toRGB'));
38 | }
39 |
40 | refresh () {
41 | this.setColorUI();
42 | this.setBackgroundColor()
43 | }
44 |
45 | setColorUI() {
46 | this.Value.setColorUI()
47 | this.Opacity.setColorUI()
48 | }
49 |
50 | '@changeColor' (sourceType) {
51 | if (source != sourceType) {
52 | this.refresh()
53 | }
54 | }
55 |
56 | '@initColor' () { this.refresh() }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/colorpicker/macos/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 |
5 | import ColorWheel from '../ui/ColorWheel'
6 | import ColorInformation from '../ui/ColorInformation'
7 | import ColorSetsChooser from '../ui/ColorSetsChooser'
8 | import CurrentColorSets from '../ui/CurrentColorSets'
9 | import CurrentColorSetsContextMenu from '../ui/CurrentColorSetsContextMenu'
10 |
11 | export default class MacOSColorPicker extends BaseColorPicker {
12 |
13 | template () {
14 | return `
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | `
24 | }
25 |
26 | components() {
27 | return {
28 | colorwheel: ColorWheel,
29 | control: ColorControl,
30 | information: ColorInformation,
31 | currentColorSets: CurrentColorSets,
32 | colorSetsChooser: ColorSetsChooser,
33 | contextMenu: CurrentColorSetsContextMenu
34 | }
35 | }
36 |
37 |
38 | }
--------------------------------------------------------------------------------
/src/colorpicker/mini-vertical/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Hue from '../ui/control/VerticalHue';
2 | import Opacity from '../ui/control/VerticalOpacity'
3 | import UIElement from '../UIElement';
4 |
5 | const source = 'mini-control';
6 |
7 | export default class ColorControl extends UIElement {
8 |
9 | components () {
10 | return { Hue, Opacity }
11 | }
12 |
13 | template () {
14 | return ``
15 | }
16 |
17 | refresh () {
18 | this.setColorUI();
19 | }
20 |
21 | setColorUI() {
22 | this.Hue.setColorUI()
23 | this.Opacity.setColorUI()
24 | }
25 |
26 | '@changeColor' (sourceType) {
27 | if (source != sourceType) {
28 | this.refresh()
29 | }
30 | }
31 |
32 | '@initColor' () { this.refresh() }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/colorpicker/mini-vertical/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 | import ColorPalette from '../ui/ColorPalette'
5 |
6 | export default class MiniColorPicker extends BaseColorPicker {
7 |
8 | template () {
9 | return `
10 |
13 | `
14 | }
15 |
16 | components() {
17 | return {
18 | palette: ColorPalette,
19 | control: ColorControl
20 | }
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/src/colorpicker/mini/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Hue from '../ui/control/Hue';
2 | import Opacity from '../ui/control/Opacity'
3 | import UIElement from '../UIElement';
4 |
5 | const source = 'mini-control';
6 |
7 | export default class ColorControl extends UIElement {
8 |
9 | components () {
10 | return { Hue, Opacity }
11 | }
12 |
13 | template () {
14 | return `
15 |
19 | `
20 | }
21 |
22 | refresh () {
23 | this.setColorUI();
24 | }
25 |
26 | setColorUI() {
27 | this.Hue.setColorUI()
28 | this.Opacity.setColorUI()
29 | }
30 |
31 | '@changeColor' (sourceType) {
32 | if (source != sourceType) {
33 | this.refresh()
34 | }
35 | }
36 |
37 | '@initColor' () { this.refresh() }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/colorpicker/mini/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 | import ColorPalette from '../ui/ColorPalette'
5 |
6 | export default class MiniColorPicker extends BaseColorPicker {
7 |
8 | template () {
9 | return `
10 |
14 | `
15 | }
16 |
17 | components() {
18 | return {
19 | palette: ColorPalette,
20 | control: ColorControl
21 | }
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/src/colorpicker/module/ColorManager.js:
--------------------------------------------------------------------------------
1 | import Color from '../../util/Color'
2 | import HueColor from '../../util/HueColor'
3 | import BaseModule from '../BaseModule';
4 |
5 |
6 | function isUndefined (v) {
7 | return typeof v == 'undefined' || v == null;
8 | }
9 |
10 | export default class ColorManager extends BaseModule {
11 |
12 | initialize () {
13 | super.initialize()
14 |
15 | this.$store.rgb = {}
16 | this.$store.hsl = {}
17 | this.$store.hsv = {}
18 | this.$store.alpha = 1
19 | this.$store.format = 'hex'
20 |
21 | // this.$store.dispatch('/changeColor');
22 | }
23 |
24 | '/changeFormat' ($store, format) {
25 | $store.format = format;
26 |
27 | $store.emit('changeFormat');
28 | }
29 |
30 | '/initColor' ($store, colorObj, source) {
31 | $store.dispatch('/changeColor', colorObj, source, true);
32 | $store.emit('initColor')
33 | }
34 |
35 | '/changeColor' ($store, colorObj, source, isNotEmit) {
36 |
37 | colorObj = colorObj || '#FF0000'
38 |
39 | if (typeof colorObj == 'string') {
40 | colorObj = Color.parse(colorObj);
41 | }
42 |
43 | colorObj.source = colorObj.source || source
44 |
45 | $store.alpha = isUndefined(colorObj.a) ? $store.alpha : colorObj.a;
46 | $store.format = colorObj.type != 'hsv' ? (colorObj.type || $store.format) : $store.format;
47 |
48 | if (colorObj.type == 'hsl') {
49 | $store.hsl = Object.assign($store.hsl, colorObj);
50 | $store.rgb = Color.HSLtoRGB($store.hsl);
51 | $store.hsv = Color.HSLtoHSV(colorObj);
52 | } else if (colorObj.type == 'hex') {
53 | $store.rgb = Object.assign($store.rgb, colorObj);
54 | $store.hsl = Color.RGBtoHSL($store.rgb);
55 | $store.hsv = Color.RGBtoHSV(colorObj);
56 | } else if (colorObj.type == 'rgb') {
57 | $store.rgb = Object.assign($store.rgb, colorObj);
58 | $store.hsl = Color.RGBtoHSL($store.rgb);
59 | $store.hsv = Color.RGBtoHSV(colorObj);
60 | } else if (colorObj.type == 'hsv') {
61 | $store.hsv = Object.assign($store.hsv, colorObj);
62 | $store.rgb = Color.HSVtoRGB($store.hsv);
63 | $store.hsl = Color.HSVtoHSL($store.hsv);
64 | }
65 |
66 | if (!isNotEmit) {
67 | $store.emit('changeColor', colorObj.source);
68 | }
69 |
70 | }
71 |
72 | '/getHueColor' ($store) {
73 | return HueColor.checkHueColor($store.hsv.h/360);
74 | }
75 |
76 | '/toString' ($store, type) {
77 | type = type || $store.format
78 | var colorObj = $store[type] || $store.rgb
79 | return Color.format({
80 | ...colorObj,
81 | a: $store.alpha
82 | }, type);
83 | }
84 |
85 | '/toColor' ($store, type) {
86 | type = type || $store.format;
87 |
88 | if (type == 'rgb') {
89 | return $store.dispatch('/toRGB')
90 | } else if (type == 'hsl') {
91 | return $store.dispatch('/toHSL')
92 | } else if (type == 'hex') {
93 | return $store.dispatch('/toHEX')
94 | }
95 |
96 | return $store.dispatch('/toString', type);
97 | }
98 |
99 | '/toRGB' ($store) {
100 | return $store.dispatch('/toString', 'rgb')
101 | }
102 |
103 | '/toHSL' ($store) {
104 | return $store.dispatch('/toString', 'hsl')
105 | }
106 |
107 | '/toHEX' ($store) {
108 | return $store.dispatch('/toString', 'hex').toUpperCase()
109 | }
110 |
111 | }
--------------------------------------------------------------------------------
/src/colorpicker/ring/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Value from '../ui/control/Value';
2 | import UIElement from '../UIElement';
3 | import Opacity from '../ui/control/Opacity'
4 | import { enableEyeDropper } from '../../util/functions/support';
5 | import Eyedropper from '../ui/Eyedropper';
6 |
7 | const source = 'macos-control';
8 |
9 | export default class ColorControl extends UIElement {
10 |
11 | components () {
12 | return { Value, Opacity, Eyedropper }
13 | }
14 |
15 | template () {
16 |
17 | const hasEyeDropper = enableEyeDropper ? 'has-eyedropper' : '';
18 | let $eyedropper = !!enableEyeDropper ? `
19 |
22 | ` : '';
23 |
24 | return `
25 |
26 |
27 |
28 |
29 |
30 | ${$eyedropper}
31 |
32 | `
33 | }
34 |
35 | setBackgroundColor () {
36 | this.refs.$controlColor.css("background-color", this.$store.dispatch('/toRGB'));
37 | }
38 |
39 | refresh () {
40 | this.setColorUI();
41 | this.setBackgroundColor()
42 | }
43 |
44 | setColorUI() {
45 | this.Value.setColorUI()
46 | this.Opacity.setColorUI()
47 | }
48 |
49 | '@changeColor' (sourceType) {
50 | if (source != sourceType) {
51 | this.refresh()
52 | }
53 | }
54 |
55 | '@initColor' () { this.refresh() }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/colorpicker/ring/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 |
5 | // import ColorWheel from '../ui/ColorWheel'
6 | import ColorInformation from '../ui/ColorInformation'
7 | import ColorSetsChooser from '../ui/ColorSetsChooser'
8 | import CurrentColorSets from '../ui/CurrentColorSets'
9 | import CurrentColorSetsContextMenu from '../ui/CurrentColorSetsContextMenu'
10 | import ColorRing from '../ui/ColorRing';
11 | import ColorPalette from '../ui/ColorPalette';
12 |
13 | export default class RingColorPicker extends BaseColorPicker {
14 |
15 | template () {
16 | return `
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | `
27 | }
28 |
29 | components() {
30 | return {
31 | colorring: ColorRing,
32 | palette: ColorPalette,
33 | control: ColorControl,
34 | information: ColorInformation,
35 | currentColorSets: CurrentColorSets,
36 | colorSetsChooser: ColorSetsChooser,
37 | contextMenu: CurrentColorSetsContextMenu
38 | }
39 | }
40 |
41 |
42 | }
--------------------------------------------------------------------------------
/src/colorpicker/ui/ColorPalette.js:
--------------------------------------------------------------------------------
1 | import UIElement from '../UIElement';
2 | import Event from '../../util/Event'
3 |
4 | const source = 'chromedevtool-palette';
5 |
6 | export default class ColorPalette extends UIElement {
7 |
8 | template () {
9 | return `
10 |
17 | `
18 | }
19 |
20 | setBackgroundColor (color) {
21 | this.$el.css("background-color", color);
22 | }
23 |
24 | refresh () {
25 | this.setColorUI();
26 | }
27 |
28 | caculateSV () {
29 | var pos = this.drag_pointer_pos || { x : 0, y : 0 };
30 |
31 | var width = this.state.get('$el.width');
32 | var height = this.state.get('$el.height');
33 |
34 | var s = (pos.x / width);
35 | var v = ((height - pos.y) / height);
36 |
37 | this.$store.dispatch('/changeColor', {
38 | type: 'hsv',
39 | s,
40 | v,
41 | source
42 | })
43 | }
44 |
45 | setColorUI() {
46 | var x = this.state.get('$el.width') * this.$store.hsv.s,
47 | y = this.state.get('$el.height') * ( 1 - this.$store.hsv.v );
48 |
49 | this.refs.$drag_pointer.css({
50 | left : x + "px",
51 | top : y + "px"
52 | });
53 |
54 | this.drag_pointer_pos = { x , y };
55 |
56 | this.setBackgroundColor(this.$store.dispatch('/getHueColor'))
57 | }
58 |
59 |
60 | setMainColor(e) {
61 | // e.preventDefault();
62 | var pos = this.$el.offset(); // position for screen
63 | var w = this.state.get('$el.contentWidth');
64 | var h = this.state.get('$el.contentHeight');
65 |
66 | var x = Event.pos(e).pageX - pos.left;
67 | var y = Event.pos(e).pageY - pos.top;
68 |
69 | if (x < 0) x = 0;
70 | else if (x > w) x = w;
71 |
72 | if (y < 0) y = 0;
73 | else if (y > h) y = h;
74 |
75 | this.refs.$drag_pointer.css({
76 | left: x + 'px',
77 | top: y + 'px'
78 | });
79 |
80 | this.drag_pointer_pos = { x , y }
81 |
82 | this.caculateSV()
83 | }
84 |
85 | '@changeColor' (sourceType) {
86 | if (source != sourceType) {
87 | this.refresh()
88 | }
89 | }
90 |
91 | '@initColor' () { this.refresh() }
92 |
93 | 'mouseup document' (e) {
94 | if (this.isDown) {
95 | this.isDown = false;
96 | this.$store.emit('lastUpdateColor');
97 | }
98 | }
99 |
100 | 'mousemove document' (e) {
101 | if (this.isDown) {
102 | this.setMainColor(e);
103 | }
104 | }
105 |
106 | mousedown (e) {
107 | this.isDown = true;
108 | this.setMainColor(e);
109 | }
110 |
111 | 'touchend document' (e) {
112 | if (this.isDown) {
113 | this.isDown = false;
114 | this.$store.emit('lastUpdateColor');
115 | }
116 | }
117 |
118 | 'touchmove document' (e) {
119 | if (this.isDown) {
120 | this.setMainColor(e);
121 | }
122 | }
123 |
124 | touchstart (e) {
125 | e.preventDefault()
126 | this.isDown = true;
127 | this.setMainColor(e);
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/ColorRing.js:
--------------------------------------------------------------------------------
1 | import ColorWheel from './ColorWheel';
2 | import { caculateAngle } from '../../util/functions/math';
3 |
4 | export default class ColorRing extends ColorWheel {
5 |
6 | constructor (opt) {
7 | super(opt)
8 |
9 | this.width = 214;
10 | this.height = 214;
11 | this.thinkness = 16;
12 | this.half_thinkness = this.thinkness / 2
13 | this.source = 'colorring'
14 | }
15 |
16 | template () {
17 | return `
18 |
22 | `
23 | }
24 |
25 | setColorUI(isEvent) {
26 | this.renderCanvas();
27 | this.setHueColor(null, isEvent);
28 | }
29 |
30 | getDefaultValue () {
31 | return this.$store.hsv.h
32 | }
33 |
34 | setHueColor (e, isEvent) {
35 |
36 | if (!this.state.get('$el.width')) return;
37 |
38 | var { minX, minY, radius, centerX, centerY } = this.getRectangle()
39 | var { x , y } = this.getCurrentXY(
40 | e,
41 | this.getDefaultValue(),
42 | radius,
43 | centerX,
44 | centerY
45 | )
46 |
47 | var rx = x - centerX, ry = y - centerY, hue = caculateAngle(rx, ry);
48 |
49 | {
50 | var { x, y } = this.getCurrentXY(null, hue, radius - this.half_thinkness, centerX, centerY);
51 | }
52 |
53 |
54 | // set drag pointer position
55 | this.refs.$drag_pointer.css({
56 | left: (x - minX) + 'px',
57 | top: (y - minY) + 'px'
58 | });
59 |
60 | if (!isEvent) {
61 | this.changeColor({
62 | type: 'hsv',
63 | h: hue
64 | })
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/ColorSetsChooser.js:
--------------------------------------------------------------------------------
1 | import UIElement from '../UIElement';
2 |
3 | const DATA_COLORSETS_INDEX = 'data-colorsets-index';
4 |
5 | export default class ColorSetsChooser extends UIElement {
6 |
7 | template () {
8 | return `
9 |
18 | `
19 | }
20 |
21 | refresh () {
22 | this.load();
23 | }
24 |
25 | '@changeCurrentColorSets' () {
26 | this.refresh()
27 | }
28 |
29 | '@toggleColorChooser' () {
30 | this.toggle()
31 | }
32 |
33 | // loadable
34 | 'load $colorsetsList' () {
35 | // colorsets
36 | const colorSets = this.$store.dispatch('/getColorSetsList');
37 |
38 | return `
39 |
40 | ${colorSets.map( (element, index) => {
41 | return `
42 |
43 |
${element.name}
44 |
45 |
46 | ${element.colors.filter((color, i) => i < 5).map(color => {
47 | color = color || 'rgba(255, 255, 255, 1)';
48 | return `
`
51 | }).join('')}
52 |
53 |
54 |
`
55 | }).join('')}
56 |
57 | `
58 | }
59 |
60 | show () {
61 | this.$el.addClass('open');
62 | }
63 |
64 | hide () {
65 | this.$el.removeClass('open');
66 | }
67 |
68 | toggle () {
69 | this.$el.toggleClass('open');
70 | }
71 |
72 |
73 | 'click $toggleButton' (e) {
74 | this.toggle();
75 | }
76 |
77 | 'click $colorsetsList .colorsets-item' (e) {
78 | const $item = e.$delegateTarget;
79 |
80 | if ($item) {
81 |
82 | const index = parseInt($item.attr(DATA_COLORSETS_INDEX));
83 |
84 | this.$store.dispatch('/setCurrentColorSets', index);
85 |
86 | this.hide();
87 | }
88 | }
89 |
90 | destroy () {
91 | super.destroy();
92 |
93 | this.hide();
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/CurrentColorSets.js:
--------------------------------------------------------------------------------
1 | import Dom from '../../util/Dom'
2 | import UIElement from '../UIElement';
3 |
4 | export default class CurrentColorSets extends UIElement {
5 |
6 | template() {
7 | return `
8 |
14 | `
15 | }
16 |
17 | 'load $colorSetsColorList' () {
18 | const currentColorSets = this.$store.dispatch('/getCurrentColorSets')
19 | const colors = this.$store.dispatch('/getCurrentColors')
20 |
21 | return `
22 |
23 | ${colors.map( (color, i) => {
24 | return `
`
28 | }).join('')}
29 | ${currentColorSets.edit ? `
+
` : ''}
30 |
31 | `
32 | }
33 |
34 | refresh () {
35 | this.load();
36 | }
37 |
38 |
39 | addColor (color) {
40 | this.$store.dispatch('/addCurrentColor', color);
41 | }
42 |
43 | '@changeCurrentColorSets' () {
44 | this.refresh()
45 | }
46 |
47 | 'click $colorSetsChooseButton' (e) {
48 | this.$store.emit('toggleColorChooser');
49 | }
50 |
51 | 'contextmenu $colorSetsColorList' (e) {
52 | e.preventDefault();
53 | const currentColorSets = this.$store.dispatch('/getCurrentColorSets')
54 |
55 | if (!currentColorSets.edit) {
56 | return;
57 | }
58 |
59 | const $target = new Dom(e.target);
60 |
61 | const $item = $target.closest('color-item');
62 |
63 | if ($item) {
64 | const index = parseInt($item.attr('data-index'));
65 |
66 | this.$store.emit('showContextMenu', e, index);
67 | } else {
68 | this.$store.emit('showContextMenu', e);
69 | }
70 | }
71 |
72 | 'click $colorSetsColorList .add-color-item' (e) {
73 | this.addColor(this.$store.dispatch('/toColor'));
74 | }
75 |
76 | 'click $colorSetsColorList .color-item' (e) {
77 | this.$store.dispatch('/changeColor', e.$delegateTarget.attr('data-color'));
78 | this.$store.emit('lastUpdateColor')
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/CurrentColorSetsContextMenu.js:
--------------------------------------------------------------------------------
1 | import Event from '../../util/Event'
2 | import UIElement from '../UIElement';
3 |
4 | export default class CurrentColorSetsContextMenu extends UIElement {
5 |
6 | template () {
7 | return `
8 |
13 | `
14 | }
15 |
16 | show (e, index) {
17 | const $event = Event.pos(e);
18 |
19 | this.$el.css({
20 | top: ($event.clientY - 10) + 'px',
21 | left: $event.clientX + 'px'
22 | });
23 | this.$el.addClass('show');
24 | this.selectedColorIndex = index;
25 |
26 | if (typeof this.selectedColorIndex == 'undefined') {
27 | this.$el.addClass('small')
28 | } else {
29 | this.$el.removeClass('small')
30 | }
31 |
32 | }
33 |
34 | hide () {
35 | this.$el.removeClass('show');
36 | }
37 |
38 | runCommand (command) {
39 | switch(command) {
40 | case 'remove-color':
41 | this.$store.dispatch('/removeCurrentColor', this.selectedColorIndex);
42 | break;
43 | case 'remove-all-to-the-right':
44 | this.$store.dispatch('/removeCurrentColorToTheRight', this.selectedColorIndex);
45 | break;
46 | case 'clear-palette':
47 | this.$store.dispatch('/clearPalette');
48 | break;
49 | }
50 | }
51 |
52 | '@showContextMenu' (e, index) {
53 | this.show(e, index)
54 | }
55 |
56 | 'click $el .menu-item' (e) {
57 | e.preventDefault();
58 |
59 | this.runCommand(e.$delegateTarget.attr('data-type'));
60 | this.hide();
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/Eyedropper.js:
--------------------------------------------------------------------------------
1 |
2 | import UIElement from '../UIElement';
3 | import './Eyedropper.scss';
4 | import { enableEyeDropper } from '../../util/functions/support';
5 |
6 | export default class Eyedropper extends UIElement {
7 |
8 | template() {
9 | return /*html*/`
10 |
17 | `;
18 | }
19 |
20 | ['click $button']() {
21 | if (enableEyeDropper) {
22 | const eyeDropper = new EyeDropper();
23 | eyeDropper.open().then(result => {
24 | this.$store.dispatch('/changeColor', result.sRGBHex);
25 | this.$store.emit('lastUpdateColor');
26 | })
27 |
28 |
29 | }
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/src/colorpicker/ui/Eyedropper.scss:
--------------------------------------------------------------------------------
1 | .el-cp-color-eyedropper {
2 | button {
3 | display: block;
4 | width: 30px;
5 | height: 30px;
6 | padding: 0;
7 | margin: -4px;
8 | font-size: 0;
9 | border: none;
10 | border-radius: var(--size-radius);
11 | cursor: pointer;
12 | outline: none;
13 | box-sizing: border-box;
14 | background: none;
15 | transition: box-shadow var(--speed-focus) ease-out, opacity var(--speed-focus) ease-out;
16 | &:focus-visible {
17 | box-shadow: 0 0 0 2px var(--color-key);
18 | }
19 | &:active {
20 | opacity: .5;
21 | }
22 | }
23 | svg {
24 | display: block;
25 | margin: 0 auto;
26 | color: var(--color-fill);
27 | }
28 | }
--------------------------------------------------------------------------------
/src/colorpicker/ui/control/Hue.js:
--------------------------------------------------------------------------------
1 | import BaseSlider from '../../BaseSlider';
2 |
3 | export default class Hue extends BaseSlider {
4 |
5 | constructor (opt) {
6 | super(opt)
7 |
8 | this.minValue = 0
9 | this.maxValue = 360
10 | this.source = 'hue-control'
11 | }
12 |
13 | template () {
14 | return `
15 |
20 | `
21 | }
22 |
23 | getDefaultValue () {
24 | return this.$store.hsv.h
25 | }
26 |
27 | refreshColorUI(e) {
28 |
29 | var dist = this.getCaculatedDist(e);
30 |
31 | this.setColorUI(dist/100 * this.maxValue);
32 |
33 | this.changeColor({
34 | h: (dist/100) * this.maxValue,
35 | type: 'hsv'
36 | })
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/control/Opacity.js:
--------------------------------------------------------------------------------
1 |
2 | import Color from '../../../util/Color'
3 | import Event from '../../../util/Event'
4 | import BaseSlider from '../../BaseSlider';
5 |
6 | const source = 'chromedevtool-control-Opacity';
7 |
8 | export default class Opacity extends BaseSlider {
9 |
10 | constructor (opt) {
11 | super(opt);
12 |
13 | this.minValue = 0;
14 | this.maxValue = 1;
15 | this.source = 'opacity-control'
16 | }
17 |
18 | template () {
19 | return `
20 |
26 | `
27 | }
28 |
29 | refresh () {
30 | super.refresh()
31 | this.setOpacityColorBar()
32 | }
33 |
34 | setOpacityColorBar() {
35 | var rgb = Object.assign({}, this.$store.rgb);
36 |
37 | rgb.a = 0;
38 | var start = Color.format(rgb, 'rgb');
39 |
40 | rgb.a = 1;
41 | var end = Color.format(rgb, 'rgb');
42 |
43 | this.setOpacityColorBarBackground(start, end);
44 | }
45 |
46 | setOpacityColorBarBackground(start, end) {
47 | this.refs.$colorbar.css('background', 'linear-gradient(to right, ' + start + ', ' + end + ')');
48 | }
49 |
50 | getDefaultValue () {
51 | return this.$store.alpha
52 | }
53 |
54 | refreshColorUI(e) {
55 | var dist = this.getCaculatedDist(e);
56 |
57 | this.setColorUI( (dist/100) * this.maxValue);
58 |
59 | this.changeColor({
60 | a: (Math.floor(dist) / 100) * this.maxValue
61 | })
62 |
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/control/Value.js:
--------------------------------------------------------------------------------
1 |
2 | import Event from '../../../util/Event'
3 | import BaseSlider from '../../BaseSlider';
4 |
5 | export default class Value extends BaseSlider {
6 |
7 | constructor (opt) {
8 | super(opt)
9 |
10 | this.minValue = 0
11 | this.maxValue = 1
12 | this.source = 'value-control'
13 | }
14 |
15 | template () {
16 | return `
17 |
22 | `
23 | }
24 |
25 | setBackgroundColor () {
26 | this.refs.$container.css("background-color", this.$store.dispatch('/toRGB'));
27 | }
28 |
29 |
30 | refresh () {
31 | super.refresh()
32 | this.setBackgroundColor();
33 | }
34 |
35 | getDefaultValue () {
36 | return this.$store.hsv.v
37 | }
38 |
39 | refreshColorUI(e) {
40 | var dist = this.getCaculatedDist(e);
41 |
42 | this.setColorUI(dist/100 * this.maxValue)
43 |
44 | this.changeColor({
45 | type: 'hsv',
46 | v: dist/100 * this.maxValue
47 | })
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/control/VerticalHue.js:
--------------------------------------------------------------------------------
1 | import VerticalSlider from '../../VerticalSlider';
2 |
3 | export default class VerticalHue extends VerticalSlider {
4 |
5 | constructor (opt) {
6 | super(opt)
7 |
8 | this.minValue = 0
9 | this.maxValue = 360
10 | this.source = 'vertical-hue-control'
11 | }
12 |
13 | template () {
14 | return `
15 |
20 | `
21 | }
22 |
23 | getDefaultValue () {
24 | return this.$store.hsv.h
25 | }
26 |
27 | refreshColorUI(e) {
28 |
29 | var dist = this.getCaculatedDist(e)
30 |
31 | this.setColorUI( dist/100 * this.maxValue);
32 |
33 | this.changeColor({
34 | h: (dist/100) * this.maxValue,
35 | type: 'hsv'
36 | })
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/colorpicker/ui/control/VerticalOpacity.js:
--------------------------------------------------------------------------------
1 |
2 | import Color from '../../../util/Color'
3 | import Event from '../../../util/Event'
4 | import VerticalSlider from '../../VerticalSlider';
5 |
6 | export default class Opacity extends VerticalSlider {
7 |
8 | constructor (opt) {
9 | super(opt)
10 |
11 | this.source = 'vertical-opacity-control'
12 | }
13 |
14 | template () {
15 | return `
16 |
22 | `
23 | }
24 |
25 | refresh () {
26 | super.refresh()
27 | this.setOpacityColorBar()
28 | }
29 |
30 | setOpacityColorBar() {
31 | var rgb = Object.assign({}, this.$store.rgb);
32 |
33 | rgb.a = 0;
34 | var start = Color.format(rgb, 'rgb');
35 |
36 | rgb.a = 1;
37 | var end = Color.format(rgb, 'rgb');
38 |
39 | this.refs.$colorbar.css('background', 'linear-gradient(to top, ' + start + ', ' + end + ')');
40 | }
41 |
42 | getDefaultValue () {
43 | return this.$store.alpha
44 | }
45 |
46 | refreshColorUI(e) {
47 | var dist = this.getCaculatedDist(e)
48 |
49 | this.setColorUI( ( dist/100 * this.maxValue) );
50 |
51 | this.changeColor({
52 | a: Math.floor(dist) / 100 * this.maxValue
53 | })
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/colorpicker/vscode/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Hue from '../ui/control/VerticalHue';
2 | import Opacity from '../ui/control/VerticalOpacity'
3 | import UIElement from '../UIElement';
4 |
5 | const source = 'mini-control';
6 |
7 | export default class ColorControl extends UIElement {
8 |
9 | components () {
10 | return { Hue, Opacity }
11 | }
12 |
13 | template () {
14 | return /*html*/`
15 |
19 | `
20 | }
21 |
22 | refresh () {
23 | this.setColorUI();
24 | }
25 |
26 | setColorUI() {
27 | this.Hue.setColorUI()
28 | this.Opacity.setColorUI()
29 | }
30 |
31 | '@changeColor' (sourceType) {
32 | if (source != sourceType) {
33 | this.refresh()
34 | }
35 | }
36 |
37 | '@initColor' () { this.refresh() }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/colorpicker/vscode/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 | import ColorPalette from '../ui/ColorPalette'
5 | import Color from '../../util/Color'
6 | import { enableEyeDropper } from '../../util/functions/support';
7 | import Eyedropper from '../ui/Eyedropper';
8 |
9 | export default class VSCodePicker extends BaseColorPicker {
10 |
11 | template () {
12 |
13 | const hasEyeDropper = enableEyeDropper ? 'has-eyedropper' : '';
14 | let $eyedropper = !!enableEyeDropper ? `
15 |
18 | ` : '';
19 |
20 | return /*html*/`
21 |
22 |
23 |
26 | ${$eyedropper}
27 |
28 |
32 |
33 | `
34 | }
35 |
36 | components() {
37 | return {
38 | palette: ColorPalette,
39 | control: ColorControl,
40 | Eyedropper
41 | }
42 | }
43 |
44 | initColorWithoutChangeEvent (color) {
45 | this.$store.dispatch('/initColor', color);
46 | this.refresh();
47 | }
48 |
49 | setBackgroundColor () {
50 | var color = this.$store.dispatch('/toColor')
51 | var rgb = this.$store.rgb;
52 | var bValue = Color.brightness(rgb.r,rgb.g,rgb.b);
53 |
54 | this.refs.$colorview.css({
55 | "background-color": color,
56 | 'color': bValue > 127 ? 'black': 'white'
57 | });
58 | this.refs.$colorview.html(color);
59 | }
60 |
61 | 'click $colorview' (e) {
62 | this.nextFormat()
63 | }
64 |
65 | nextFormat() {
66 | var current_format = this.$store.format || 'hex';
67 |
68 | var next_format = 'hex';
69 | if (current_format == 'hex') {
70 | next_format = 'rgb';
71 | } else if (current_format == 'rgb') {
72 | next_format = 'hsl';
73 | } else if (current_format == 'hsl') {
74 | next_format = 'hex';
75 | }
76 |
77 | this.$store.dispatch('/changeFormat', next_format);
78 | this.$store.emit('lastUpdateColor')
79 | this.refresh();
80 | }
81 |
82 | refresh () {
83 | this.setBackgroundColor()
84 | }
85 |
86 | '@changeColor' () {
87 | this.refresh()
88 | }
89 |
90 | '@initColor' () {
91 | this.refresh()
92 | }
93 |
94 |
95 |
96 | }
--------------------------------------------------------------------------------
/src/colorpicker/xd/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Hue from '../ui/control/VerticalHue';
2 | import Opacity from '../ui/control/VerticalOpacity'
3 | import UIElement from '../UIElement';
4 |
5 | export default class ColorControl extends UIElement {
6 |
7 | components () {
8 | return { Hue, Opacity }
9 | }
10 |
11 | template () {
12 | return `
13 |
17 | `
18 | }
19 |
20 | refresh () {
21 | this.setColorUI();
22 | }
23 |
24 | setColorUI() {
25 | this.Hue.setColorUI()
26 | this.Opacity.setColorUI()
27 | }
28 |
29 | '@changeColor' () {
30 | this.refresh()
31 | }
32 |
33 | '@initColor' () { this.refresh() }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/colorpicker/xd/index.js:
--------------------------------------------------------------------------------
1 | import BaseColorPicker from '../BaseColorPicker'
2 |
3 | import ColorControl from './ColorControl'
4 | import ColorInformation from '../ui/ColorInformation'
5 | import ColorPalette from '../ui/ColorPalette'
6 | import ColorSetsChooser from '../ui/ColorSetsChooser'
7 | import CurrentColorSets from '../ui/CurrentColorSets'
8 | import CurrentColorSetsContextMenu from '../ui/CurrentColorSetsContextMenu'
9 |
10 | export default class XDColorPicker extends BaseColorPicker {
11 |
12 | template () {
13 | return `
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | `
23 | }
24 |
25 | components() {
26 | return {
27 | palette: ColorPalette,
28 | control: ColorControl,
29 | information: ColorInformation,
30 | currentColorSets: CurrentColorSets,
31 | colorSetsChooser: ColorSetsChooser,
32 | contextMenu: CurrentColorSetsContextMenu
33 | }
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/src/extension/codemirror/index.js:
--------------------------------------------------------------------------------
1 | import CodeMirrorColorView from './colorview'
2 |
3 | try {
4 | var CodeMirror = require('codemirror')
5 | } catch(e) { }
6 |
7 | const CHECK_CODEMIRROR_OBJECT = () => (CodeMirror || window.CodeMirror);
8 | function LOAD_CODEMIRROR_COLORPICKER () {
9 | var CODEMIRROR_OBJECT = CHECK_CODEMIRROR_OBJECT();
10 |
11 | if (CODEMIRROR_OBJECT) {
12 | CODEMIRROR_OBJECT.defineOption("colorpicker", false, function (cm, val, old) {
13 | if (old && old != CODEMIRROR_OBJECT.Init) {
14 |
15 | if (cm.state.colorpicker)
16 | {
17 | cm.state.colorpicker.destroy();
18 | cm.state.colorpicker = null;
19 |
20 | }
21 | // remove event listener
22 | }
23 |
24 | if (val)
25 | {
26 | cm.state.colorpicker = new CodeMirrorColorView(cm, val);
27 | }
28 | });
29 | }
30 |
31 | }
32 |
33 | LOAD_CODEMIRROR_COLORPICKER()
34 |
35 | export default {
36 | load: LOAD_CODEMIRROR_COLORPICKER
37 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import './scss/index.scss'
2 |
3 | import Util from './util/index'
4 | import ColorPicker from './colorpicker/index'
5 | import CodeMirrorExtension from './extension/codemirror/index'
6 |
7 |
8 | export default {
9 | ...Util,
10 | ...ColorPicker,
11 | ...CodeMirrorExtension
12 | }
--------------------------------------------------------------------------------
/src/scss/colorpicker.scss:
--------------------------------------------------------------------------------
1 |
2 | /* codemirror-colorpicker */
3 |
4 | .codemirror-colorpicker {
5 | position: relative;
6 | width: 224px;
7 | z-index: 1000;
8 | display:inline-block;
9 | border: 1px solid rgba(0, 0, 0, 0.2);
10 | background-color: #fff;
11 | border-radius: 3px;
12 | box-shadow: 0 0px 10px 2px rgba(0, 0, 0, 0.12);
13 |
14 | > .arrow {
15 | position: absolute;
16 | top: -10px;
17 | left: 7px;
18 | width: 0;
19 | height: 0;
20 | border-left: 10px solid transparent;
21 | border-right: 10px solid transparent;
22 | display:none;
23 |
24 | border-bottom: 10px solid rgba(0, 0, 0, 0.2);
25 | pointer-events: none;
26 | &:after {
27 | position: absolute;
28 | content: "";
29 | top: 1px;
30 | left: -9px;
31 | width: 0;
32 | height: 0;
33 | border-left: 9px solid transparent;
34 | border-right: 9px solid transparent;
35 |
36 | border-bottom: 9px solid white;
37 | }
38 | }
39 |
40 | .colorpicker-body {
41 | @import './component/button';
42 | @import './component/palette';
43 | @import './component/control';
44 | @import './component/information';
45 | @import './component/colorsets';
46 | @import './component/colorchooser';
47 |
48 | }
49 |
50 | &.chromedevtool {
51 |
52 | }
53 |
54 | /* theme */
55 | @import './themes/sketch';
56 | @import './themes/palette';
57 | @import './themes/macos';
58 | @import './themes/mini';
59 | @import './themes/mini-vertical';
60 | @import './themes/ring';
61 | @import './themes/xd';
62 | @import './themes/vscode';
63 | @import './themes/box';
64 | }
65 |
66 | @import './component/colorsets-contextmenu';
67 |
--------------------------------------------------------------------------------
/src/scss/colorview.scss:
--------------------------------------------------------------------------------
1 | /* codemirror colorview */
2 |
3 | .codemirror-colorview {
4 | border : 1px solid #cecece;
5 | position: relative;
6 | display : inline-block;
7 | box-sizing : border-box;
8 | margin : 0px 2px;
9 | width : 10px;
10 | height : 10px;
11 | cursor: pointer;
12 | vertical-align: middle;
13 | @include transparent-background();
14 |
15 | .codemirror-colorview-background {
16 | content: "";
17 | position: absolute;
18 | left:0px;
19 | right:0px;
20 | bottom:0px;
21 | top:0px;
22 | }
23 |
24 | &:hover {
25 | border-color: #494949;
26 | }
27 | }
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/scss/component/button.scss:
--------------------------------------------------------------------------------
1 | .arrow-button {
2 | position: relative;
3 | width: 10px;
4 | height: 12px;
5 | padding: 0px;
6 | background-color: transparent;
7 |
8 | &:before {
9 | content: "";
10 | display:inline-block;
11 | position:absolute;
12 | left:0px;
13 | right:0px;
14 | top:0px;
15 | height:50%;
16 | @include arrow_top(3px, black);
17 | margin: 2px;
18 | box-sizing:border-box;
19 | }
20 |
21 | &:after {
22 | content: "";
23 | display:inline-block;
24 | position:absolute;
25 | left:0px;
26 | right:0px;
27 | bottom:0px;
28 | top:50%;
29 | @include arrow_bottom(3px, black);
30 | margin: 2px;
31 | box-sizing:border-box;
32 | }
33 | }
--------------------------------------------------------------------------------
/src/scss/component/colorsets-contextmenu.scss:
--------------------------------------------------------------------------------
1 |
2 | .colorsets-contextmenu {
3 | position:fixed;
4 | padding-top:4px;
5 | padding-bottom:4px;
6 | border-radius: 6px;
7 | background-color: #ececec;
8 | border: 1px solid rgba(204, 204, 204, 1);
9 | display: none;
10 | list-style: none;
11 | font-size: 13px;
12 | padding-left: 0px;
13 | padding-right: 0px;
14 | &.show {
15 | display:inline-block;
16 | }
17 |
18 | .menu-item {
19 | padding: 2px 20px;
20 | cursor: default;
21 |
22 | &:hover {
23 | background-color: #5ea3fb;
24 | color: white;
25 | }
26 | }
27 |
28 | &.small {
29 | .menu-item.small-hide {
30 | display: none;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/scss/component/colorsets.scss:
--------------------------------------------------------------------------------
1 |
2 | .colorsets {
3 | border-top: 1px solid #e2e2e2;
4 |
5 | > .menu {
6 | float: right;
7 | padding: 10px 5px;
8 | padding-right: 15px;
9 |
10 | button {
11 | border:0px;
12 | font-size: 14px;
13 | font-weight: 300;
14 | font-family: serif, sans-serif;
15 | outline:none;
16 | cursor: pointer;
17 | }
18 | }
19 |
20 | > .color-list {
21 | margin-right: 30px;
22 | display: block;
23 | padding: 12px 0px 0px 12px;
24 | box-sizing:border-box;
25 | line-height: 0;
26 |
27 | .color-item {
28 | width: 13px;
29 | height: 13px;
30 | border-radius:2px;
31 | display:inline-block;
32 | margin-right:12px;
33 | margin-bottom:12px;
34 | position:relative;
35 | background-size: contain;
36 | overflow:hidden;
37 | box-sizing:border-box;
38 | cursor: pointer;
39 | vertical-align: middle;
40 |
41 | &:hover {
42 | transform: scale(1.2);
43 | }
44 |
45 | .empty {
46 | position: absolute;
47 | left:0px;
48 | top:0px;
49 | @include transparent-background();
50 | width: 100%;
51 | height: 100%;
52 | padding: 0px;
53 | margin: 0px;
54 | pointer-events: none;
55 | }
56 |
57 | .color-view {
58 | position: absolute;
59 | left:0px;
60 | top:0px;
61 | width: 100%;
62 | height: 100%;
63 | padding:0px;
64 | margin:0px;
65 | pointer-events: none;
66 | border: 1px solid rgba(0, 0, 0, 0.1);
67 | box-sizing: border-box;
68 | }
69 | }
70 |
71 | .add-color-item {
72 | width: 13px;
73 | height: 13px;
74 | display:inline-block;
75 | margin-right:12px;
76 | margin-bottom:12px;
77 | cursor: pointer;
78 | line-height: 1;
79 | text-align: center;
80 | font-size: 16px;
81 | font-weight: 400;
82 | font-family: serif,sans-serif;
83 | color: rgb(142, 142, 142);
84 | vertical-align: middle;
85 | }
86 | }
87 |
88 |
89 | }
--------------------------------------------------------------------------------
/src/scss/component/control.scss:
--------------------------------------------------------------------------------
1 | .control {
2 | position: relative;
3 | padding: 10px 0px 10px 0px;
4 | user-select: none;
5 |
6 | &.has-eyedropper {
7 | padding-left: 30px;
8 |
9 | .el-cp-color-control__left {
10 | position: absolute;
11 | left: 12px;
12 | top: 20px;
13 | width: 30px;
14 | height: 30px;
15 | border-radius: 50%;
16 | box-sizing: border-box;
17 | }
18 |
19 | > .color, > .empty {
20 | left: 45px;
21 | }
22 | }
23 |
24 |
25 | > .color, > .empty {
26 | position: absolute;
27 | left: 12px;
28 | top: 14px;
29 | width: 30px;
30 | height: 30px;
31 | border-radius: 50%;
32 | box-sizing: border-box;
33 | }
34 |
35 | > .color {
36 | border: 1px solid rgba(0, 0, 0, 0.1);
37 | }
38 |
39 | > .hue {
40 | position: relative;
41 | padding: 6px 16px;
42 | margin: 0px 0px 0px 42px;
43 | box-sizing: border-box;
44 | cursor: pointer;
45 |
46 | > .hue-container {
47 | position: relative;
48 | width: 100%;
49 | height: 10px;
50 | border-radius: 3px;
51 | }
52 | }
53 |
54 |
55 | > .opacity {
56 | position: relative;
57 | padding: 3px 16px;
58 | margin: 0px 0px 0px 42px;
59 | box-sizing: border-box;
60 | cursor: pointer;
61 |
62 | > .opacity-container {
63 | position: relative;
64 | width: 100%;
65 | height: 10px;
66 | border-radius: 3px;
67 | }
68 | }
69 |
70 | .drag-bar, .drag-bar2 {
71 | position: absolute;
72 | cursor: pointer;
73 | top: 50%;
74 | left: 0px;
75 | transform: translateX(-50%) translateY(-50%);
76 | width: 12px;
77 | height: 12px;
78 | border-radius: 50%;
79 | }
80 |
81 | > .hue > .hue-container {
82 | background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
83 | }
84 |
85 | > .opacity > .opacity-container {
86 | @include transparent-background();
87 |
88 | > .color-bar {
89 | position:absolute;
90 | display:block;
91 | content:"";
92 | left:0px;
93 | right:0px;
94 | bottom:0px;
95 | top:0px;
96 | }
97 | }
98 |
99 | > .empty {
100 | @include transparent-background();
101 | }
102 |
103 | .drag-bar,
104 | .drag-bar2 {
105 | border: 1px solid rgba(0, 0, 0, 0.05);
106 | box-shadow: 2px 2px 2px 0px rgba(0, 0, 0, 0.2);
107 | background-color: #fefefe;
108 |
109 | }
110 |
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/src/scss/component/information.scss:
--------------------------------------------------------------------------------
1 | .information {
2 | /*border-top: 1px solid #e8e8e8;*/
3 | position: relative;
4 | box-sizing: padding-box;
5 |
6 | > input {
7 | position: absolute;
8 | font-size: 10px;
9 | height: 20px;
10 | bottom: 20px;
11 | padding: 0 0 0 2px;
12 | box-sizing: border-box;
13 | user-select: text;
14 |
15 | &[type=number] {
16 | appearance: none;
17 | }
18 |
19 | &[type=number]::-webkit-inner-spin-button,
20 | &[type=number]::-webkit-outer-spin-button
21 | {
22 | appearance: none;
23 | margin: 0;
24 | }
25 | }
26 |
27 | &.hex > .information-item.hex {
28 | display: flex;
29 | }
30 |
31 | &.rgb > .information-item.rgb {
32 | display: flex;
33 | }
34 |
35 | &.hsl > .information-item.hsl {
36 | display: flex;
37 | }
38 |
39 | > .information-item {
40 | display:none;
41 | position: relative;
42 | padding: 0px 5px;
43 | padding-left: 9px;
44 | box-sizing: border-box;
45 | margin-right:40px;
46 |
47 | > .input-field {
48 | display:block;
49 | flex:1;
50 | padding: 3px;
51 | box-sizing: border-box;
52 | position: relative;
53 |
54 | > .title {
55 | text-align:center;
56 | font-size:12px;
57 | color:#a9a9a9;
58 | padding-top:2px;
59 | cursor: pointer;
60 | user-select: none;
61 | }
62 |
63 | input {
64 | text-align: center;
65 | width:100%;
66 | padding:3px;
67 | height: 21px;
68 | font-size:11px;
69 | color: #333;
70 | box-sizing: border-box;
71 | user-select: text;
72 | border: 1px solid #cbcbcb;
73 | border-radius:2px;
74 |
75 | &[type=number] {
76 | appearance: none;
77 | }
78 |
79 | &[type=number]::-webkit-inner-spin-button,
80 | &[type=number]::-webkit-outer-spin-button
81 | {
82 | appearance: none;
83 | margin: 0;
84 | }
85 | }
86 |
87 | &.hsl-l,
88 | &.hsl-s {
89 |
90 | input[type=number] {
91 | padding-left: 1px;
92 | padding-right: 10px;
93 |
94 | }
95 |
96 | }
97 |
98 | .postfix {
99 | display:inline-block;
100 | position: absolute;
101 | right:3px;
102 | top:2px;
103 | height: 21px;
104 | line-height: 2;
105 | padding: 2px;
106 | box-sizing: border-box;
107 | text-align:center;
108 | font-size: 11px;
109 | }
110 | }
111 | }
112 |
113 | > .information-change {
114 | position:absolute;
115 | display:block;
116 | width:40px;
117 | top:0px;
118 | right:0px;
119 | bottom:0px;
120 | text-align: center;
121 | box-sizing: border-box;
122 | padding-top:5px;
123 |
124 | > .format-change-button {
125 | box-sizing: border-box;
126 | background:transparent;
127 | border:0px;
128 | cursor:pointer;
129 | outline:none;
130 | }
131 | }
132 |
133 | > .title {
134 | color: #a3a3a3;
135 | }
136 |
137 | > .input {
138 | color: #333;
139 | }
140 |
141 | }
--------------------------------------------------------------------------------
/src/scss/component/palette.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | .color {
4 | position: relative;
5 | height: 120px;
6 | overflow: hidden;
7 | cursor: pointer;
8 |
9 | > .saturation {
10 | position: relative;
11 | width: 100%;
12 | height: 100%;
13 |
14 | > .value {
15 | position: relative;
16 | width: 100%;
17 | height: 100%;
18 |
19 | > .drag-pointer {
20 | position: absolute;
21 | width: 10px;
22 | height: 10px;
23 | border-radius: 50%;
24 | transform: translateX(-50%) translateY(-50%);
25 | }
26 | }
27 |
28 | }
29 |
30 | > .saturation {
31 | background-color: rgba(204, 154, 129, 0);
32 | background-image: linear-gradient(to right, #FFF, rgba(204, 154, 129, 0));
33 | background-repeat: repeat-x;
34 |
35 | > .value {
36 | background-image: linear-gradient(to top, #000000, rgba(204, 154, 129, 0));
37 |
38 | > .drag-pointer {
39 | border: 1px solid #fff;
40 | box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.05);
41 | }
42 | }
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/src/scss/index.scss:
--------------------------------------------------------------------------------
1 | @import './mixins';
2 |
3 | @import './colorview';
4 | @import './colorpicker';
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/scss/mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin transparent-background () {
2 | background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC") repeat;
3 | }
4 |
5 | @mixin arrow_top ($pixel, $color) {
6 | width: 0;
7 | height: 0;
8 | border-left: $pixel solid transparent;
9 | border-right: $pixel solid transparent;
10 | border-bottom: $pixel solid $color;
11 | pointer-events: none;
12 | }
13 |
14 | @mixin arrow_bottom ($pixel, $color) {
15 | width: 0;
16 | height: 0;
17 | border-left: $pixel solid transparent;
18 | border-right: $pixel solid transparent;
19 | border-top: $pixel solid $color;
20 | pointer-events: none;
21 | }
--------------------------------------------------------------------------------
/src/scss/themes/box.scss:
--------------------------------------------------------------------------------
1 | &.box {
2 | width: 420px;
3 | border-radius: 10px;
4 | .colorpicker-body {
5 | display: grid;
6 | padding: 10px 20px 10px 10px;
7 | grid-template-columns: 200px 1fr;
8 | column-gap: 10px;
9 | grid-template-rows: auto;
10 |
11 | > .color {
12 | height: 100%;
13 | border-radius: 8px;
14 | overflow: hidden;
15 | }
16 | }
17 |
18 | .control {
19 | padding: 0px !important;
20 |
21 | > * {
22 | vertical-align: middle;
23 | }
24 |
25 | .color-info {
26 | position: relative;
27 | height: 30px;
28 | width: 30px;
29 | display: inline-block;
30 |
31 | > .color, > .empty {
32 | position: absolute;
33 | width: 100%;
34 | height: 100%;
35 | border-radius: 50%;
36 | box-sizing: border-box;
37 | }
38 |
39 | > .color {
40 | border: 1px solid rgba(0, 0, 0, 0.1);
41 | }
42 |
43 | }
44 |
45 | > .color, > .empty {
46 | top: 4px;
47 | }
48 |
49 | &.has-eyedropper {
50 | padding-left: 30px;
51 |
52 | .el-cp-color-control__left {
53 | display: inline-block;
54 | width: 30px;
55 | height: 30px;
56 | position: relative;
57 | top: auto;
58 | left: auto;
59 | }
60 | }
61 |
62 | .hue, .opacity {
63 | padding-left: 0px !important;
64 | margin-left: 0px !important;
65 | padding-right: 0px !important;
66 | }
67 |
68 | }
69 |
70 |
71 | .value {
72 | position: relative;
73 | // padding: 6px 16px;
74 | // margin: 0px 0px 0px 42px;
75 | box-sizing: border-box;
76 | cursor: pointer;
77 |
78 | > .value-container {
79 | position: relative;
80 | width: 100%;
81 | height: 10px;
82 | border-radius: 3px;
83 | background-image: linear-gradient(to right, #000000 0%, rgba(255, 255, 255, 0) 100%);
84 | box-sizing: border-box;
85 |
86 | .drag-bar {
87 | position: absolute;
88 | cursor: pointer;
89 | top: 50%;
90 | left: 0px;
91 | transform: translateX(-50%) translateY(-50%);
92 | width: 12px;
93 | height: 12px;
94 | border-radius: 50%;
95 | }
96 |
97 | }
98 | }
99 |
100 | .information {
101 | margin-top: 6px;
102 | .information-change {
103 | display: none;
104 | }
105 |
106 | > .information-item {
107 | margin: 0px !important;
108 | padding: 0px !important;
109 | }
110 | }
111 |
112 | .colorsets {
113 | border: 0px;
114 | position: relative;
115 |
116 | .color-list {
117 | padding: 0px !important;
118 | margin-right: 0px !important;
119 |
120 | .current-color-sets {
121 | .color-item {
122 | width: 20px;
123 | height: 20px;
124 | margin-right: 4px !important;
125 | margin-bottom: 4px !important;
126 | }
127 | }
128 | }
129 |
130 | .menu {
131 | float: none;
132 | position: absolute;
133 | right: -20px;
134 | top: -15px;
135 | }
136 | }
137 |
138 | .color-chooser .color-chooser-container {
139 | top: 0px;
140 | left: 200px;
141 | }
142 |
143 | }
--------------------------------------------------------------------------------
/src/scss/themes/macos.scss:
--------------------------------------------------------------------------------
1 | &.macos {
2 | .colorpicker-body {
3 | .wheel {
4 | width: 224px;
5 | height: 224px;
6 | position: relative;
7 | box-sizing: border-box;
8 |
9 | .wheel-canvas {
10 | width: 214px;
11 | height: 214px;
12 | border-radius: 50%;
13 | position: absolute;
14 | left:5px;
15 | top:5px;
16 | }
17 |
18 | .drag-pointer {
19 | display:inline-block;
20 | position: absolute;
21 | width: 10px;
22 | height: 10px;
23 | left:50%;
24 | top:50%;
25 | border:1px solid white;
26 | border-radius: 50%;
27 | transform: translateX(-50%) translateY(-50%);
28 | z-index:2;
29 | }
30 | }
31 |
32 | }
33 |
34 | .control {
35 | padding-top: 0px;
36 |
37 | > .color, > .empty {
38 | top: 4px;
39 | }
40 |
41 | &.has-eyedropper {
42 | padding-left: 30px;
43 |
44 | .el-cp-color-control__left {
45 | top: 9px;
46 | }
47 | }
48 |
49 | }
50 |
51 |
52 | .value {
53 | position: relative;
54 | padding: 6px 16px;
55 | margin: 0px 0px 0px 42px;
56 | box-sizing: border-box;
57 | cursor: pointer;
58 |
59 | > .value-container {
60 | position: relative;
61 | width: 100%;
62 | height: 10px;
63 | border-radius: 3px;
64 | background-image: linear-gradient(to right, #000000 0%, rgba(255, 255, 255, 0) 100%);
65 | box-sizing: border-box;
66 |
67 | .drag-bar {
68 | position: absolute;
69 | cursor: pointer;
70 | top: 50%;
71 | left: 0px;
72 | transform: translateX(-50%) translateY(-50%);
73 | width: 12px;
74 | height: 12px;
75 | border-radius: 50%;
76 | }
77 |
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/src/scss/themes/mini-vertical.scss:
--------------------------------------------------------------------------------
1 | &.mini-vertical {
2 | width: 180px;
3 | display: inline-block;
4 |
5 | .color {
6 | display:inline-block;
7 | width: 140px;
8 | height: 160px;
9 | vertical-align: middle;
10 | }
11 |
12 | .control {
13 | height: 160px;
14 | padding: 0px;
15 | vertical-align: middle;
16 | display:inline-block;
17 |
18 | .hue, .opacity {
19 | margin: 0px;
20 | padding:0px;
21 | width: 20px;
22 | display:inline-block;
23 | vertical-align: middle;
24 | height: 100%;
25 | position: relative;
26 | }
27 |
28 | .hue > .hue-container {
29 | border-radius:0px;
30 | overflow:hidden;
31 | height: 100%;
32 | background: linear-gradient(to top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
33 | }
34 |
35 |
36 | .opacity > .opacity-container {
37 | border-radius: 0px;
38 | overflow: hidden;
39 | height: 100%;
40 | width: 20px;
41 | }
42 |
43 |
44 | .drag-bar, .drag-bar2 {
45 | border:0px;
46 | background-color: transparent;
47 | height:2px;
48 | width:100%;
49 | box-sizing: border-box;
50 | box-shadow: none;
51 | transform: none;
52 |
53 | &.last {
54 | &:before, &:after {
55 | top: 2px;
56 | }
57 | }
58 |
59 | &.first {
60 | &:before, &:after {
61 | top: -1px;
62 | }
63 | }
64 |
65 | &:before {
66 | content: "";
67 | position: absolute;
68 | left: 0px;
69 | top: 2px;
70 | width: 0;
71 | height: 0;
72 | transform: translateY(-50%);
73 | border-top: 4px solid transparent;
74 | border-bottom: 4px solid transparent;
75 | border-left: 4px solid black;
76 | }
77 |
78 | &:after {
79 | content: "";
80 | position: absolute;
81 | top: 2px;
82 | right: 0px;
83 | width: 0;
84 | height: 0;
85 | transform: translateY(-50%);
86 | border-top: 4px solid transparent;
87 | border-bottom: 4px solid transparent;
88 | border-right: 4px solid black;
89 | }
90 | }
91 |
92 | }
93 |
94 | }
--------------------------------------------------------------------------------
/src/scss/themes/mini.scss:
--------------------------------------------------------------------------------
1 | &.mini {
2 | width: 180px;
3 | display: inline-block;
4 |
5 | .control {
6 | padding: 0px;
7 |
8 |
9 | .hue, .opacity {
10 | margin: 0px;
11 | padding:0px;
12 | }
13 |
14 | .hue > .hue-container {
15 | border-radius:0px;
16 | overflow:hidden;
17 | height: 20px;
18 | }
19 |
20 | .opacity > .opacity-container {
21 | border-radius: 0px;
22 | overflow: hidden;
23 | height: 20px;
24 | }
25 |
26 |
27 | .drag-bar, .drag-bar2 {
28 | border:0px;
29 | background-color: transparent;
30 | height:100%;
31 | width:5px;
32 | box-sizing: border-box;
33 | box-shadow: none;
34 |
35 | &.last {
36 | &:before, &after {
37 | left: 1px;
38 | }
39 | }
40 |
41 | &.first {
42 | &:before, &:after {
43 | left: 3px;
44 | }
45 | }
46 |
47 | &:before {
48 | content: "";
49 | position: absolute;
50 | left: 2px;
51 | top: 0px;
52 | width: 0;
53 | height: 0;
54 | transform: translateX(-50%);
55 | border-left: 4px solid transparent;
56 | border-right: 4px solid transparent;
57 | border-top: 4px solid black;
58 | }
59 |
60 | &:after {
61 | content: "";
62 | position: absolute;
63 | left: 2px;
64 | bottom: 0px;
65 | width: 0;
66 | height: 0;
67 | transform: translateX(-50%);
68 | border-left: 4px solid transparent;
69 | border-right: 4px solid transparent;
70 | border-bottom: 4px solid black;
71 | }
72 | }
73 |
74 | }
75 |
76 | }
--------------------------------------------------------------------------------
/src/scss/themes/palette.scss:
--------------------------------------------------------------------------------
1 | &.palette {
2 | border-radius: 3px;
3 | box-shadow: none;
4 |
5 | > .colorpicker-body {
6 |
7 | > .color {
8 | display: none;
9 | }
10 |
11 | > .control {
12 | display: none;
13 | }
14 |
15 | > .information {
16 | display: none;
17 | }
18 |
19 | > .colorsets {
20 | box-sizing: border-box;
21 | border-top:0px;
22 |
23 | > .color-list {
24 | .color-item {
25 | width: 15px;
26 | height: 15px;
27 | margin-right: 10px;
28 | margin-bottom: 10px;
29 | }
30 | }
31 | }
32 |
33 | > .color-chooser {
34 | display: none;
35 | box-sizing: border-box;
36 | &.open {
37 | display: block;
38 | top:-1px;
39 | left:-1px;
40 | right:-1px;
41 | bottom: auto;
42 | border-radius: 3px;
43 | border: 1px solid #d8d8d8;
44 | box-shadow: 0 0px 10px 2px rgba(0, 0, 0, 0.12);
45 | .color-chooser-container {
46 | position: relative;
47 | top: auto;
48 | left: auto;
49 | right: auto;
50 | bottom: auto;
51 | background-color: white;
52 | box-sizing: border-box;
53 | border-radius: 2px;
54 |
55 | .colorsets-item-header {
56 | position: relative;
57 | left:auto;
58 | top:auto;
59 | right:auto;
60 | bottom:auto;
61 | border-top-left-radius: 3px;
62 | border-top-right-radius: 3px;
63 | }
64 |
65 | .colorsets-list {
66 | position: relative;
67 | top: auto;
68 | left: auto;
69 | right: auto;
70 | bottom: auto;
71 | overflow: auto;
72 |
73 | .colorsets-item:last-child {
74 | border-bottom-left-radius: 3px;
75 | border-bottom-right-radius: 3px;
76 | }
77 | }
78 | }
79 | }
80 | }
81 |
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/scss/themes/ring.scss:
--------------------------------------------------------------------------------
1 | &.ring {
2 | .colorpicker-body {
3 |
4 | > .color {
5 | position: absolute;
6 | width: 120px;
7 | height: 120px;
8 | left: 52px;
9 | top: 52px;
10 | }
11 |
12 | .wheel {
13 | width: 224px;
14 | height: 224px;
15 | position: relative;
16 | box-sizing: border-box;
17 |
18 | .wheel-canvas {
19 | width: 214px;
20 | height: 214px;
21 | border-radius: 50%;
22 | position: absolute;
23 | left:5px;
24 | top:5px;
25 | }
26 |
27 | .drag-pointer {
28 | display:inline-block;
29 | position: absolute;
30 | width: 10px;
31 | height: 10px;
32 | left:50%;
33 | top:50%;
34 | border:1px solid white;
35 | border-radius: 50%;
36 | transform: translateX(-50%) translateY(-50%);
37 | z-index:2;
38 | }
39 | }
40 |
41 | }
42 |
43 | .control {
44 | padding-top: 0px;
45 |
46 | .value {
47 | display: none;
48 | }
49 |
50 | > .color, > .empty {
51 | top: -17px;
52 | width: 30px;
53 | height: 30px;
54 | border-radius: 2px;
55 | }
56 |
57 |
58 | &.has-eyedropper {
59 | padding-left: 30px;
60 | padding-top: 10px;
61 |
62 | > .color, > .empty {
63 | top: -2px;
64 | }
65 |
66 | .el-cp-color-control__left {
67 | top: 4px;
68 | }
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/src/scss/themes/vscode.scss:
--------------------------------------------------------------------------------
1 | &.vscode {
2 | width: 336px;
3 | display: inline-block;
4 | background-color: #333;
5 | border: 1px solid #ececec;
6 | box-sizing: border-box;
7 | border-radius: 0px;
8 |
9 | .colorpicker-body {
10 | border-radius: 0px;
11 | display: inline-block;
12 |
13 | .color-view {
14 | height: 34px;
15 |
16 | &.has-eyedropper {
17 | display: flex;
18 | .color-view-container {
19 | width: 254px;
20 | display: inline-block;
21 | }
22 |
23 |
24 | .el-cp-color-control__left {
25 | float: right;
26 | width: 80px;
27 | text-align: center;
28 | padding: 6px 0px;
29 |
30 | button {
31 | display: inline-block;
32 |
33 | svg {
34 | path {
35 | fill: white;
36 | }
37 | }
38 | }
39 | }
40 | }
41 |
42 | .color-view-container {
43 | line-height: 34px;
44 | font-size: 14px;
45 | text-align: center;
46 | width: 100%;
47 | height: 100%;
48 | cursor: pointer;
49 | user-select: none;
50 | text-shadow: 0 0 3px rgb(83, 83, 83);
51 | @include transparent-background();
52 |
53 | .preview {
54 | display: block;
55 | height: 100%;
56 | }
57 | }
58 | }
59 |
60 | .color-tool {
61 | padding: 8px;
62 | }
63 | }
64 |
65 | .color {
66 | display:inline-block;
67 | width: 240px;
68 | height: 160px;
69 | vertical-align: middle;
70 | }
71 |
72 | .control {
73 | height: 160px;
74 | vertical-align: middle;
75 | display:inline-block;
76 | padding: 0px 0px 0px 4px;
77 |
78 | .hue, .opacity {
79 | margin: 0px;
80 | padding:0px;
81 | width: 30px;
82 | display:inline-block;
83 | vertical-align: middle;
84 | height: 100%;
85 | position: relative;
86 | }
87 |
88 |
89 | .hue {
90 | padding-left: 5px;
91 | width: 35px;
92 | }
93 |
94 | .hue > .hue-container {
95 | border-radius:0px;
96 | height: 100%;
97 | background: linear-gradient(to top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
98 | }
99 |
100 |
101 | .opacity > .opacity-container {
102 | border-radius: 0px;
103 | height: 100%;
104 | width: 30px;
105 | }
106 |
107 |
108 | .drag-bar, .drag-bar2 {
109 | background-color: transparent;
110 | height:5px;
111 | width:33px;
112 | box-sizing: border-box;
113 | box-shadow: none;
114 | transform: translateY(-50%) translateX(-2px);
115 | border: 1px solid rgba(255, 255, 255, 1);
116 | border-radius: 0px;
117 | box-shadow: 0 0 2px 0 rgba(0, 0, 0, 1), inset 0 0 0 0 rgba(0, 0, 0, 1);
118 |
119 |
120 | }
121 |
122 | }
123 |
124 | }
--------------------------------------------------------------------------------
/src/scss/themes/xd.scss:
--------------------------------------------------------------------------------
1 | &.xd {
2 | display: inline-block;
3 | // padding: 12px;
4 | padding-top: 12px;
5 | width: 245px;
6 |
7 | .color {
8 | display:inline-block;
9 | margin-left: 12px;
10 | margin-bottom: 12px;
11 | width: 170px;
12 | height: 170px;
13 | vertical-align: middle;
14 | border-radius: 3px;
15 | overflow: hidden;
16 | box-sizing: border-box;
17 | border: 1px solid #cecece;
18 |
19 | > .saturation {
20 | > .value {
21 | > .drag-pointer {
22 | border: 2px solid white;
23 | width: 7px;
24 | height: 7px;
25 | box-shadow: 0 0 1px 0px rgba(0, 0, 0, 1), inset 0 0 1px 0px rgba(0, 0, 0, 1);
26 | }
27 | }
28 | }
29 |
30 | }
31 |
32 | .control {
33 | height: 170px;
34 | padding: 0px;
35 | vertical-align: middle;
36 | display:inline-block;
37 | margin-right: 12px;
38 | margin-bottom: 12px;
39 |
40 | .hue, .opacity {
41 | margin: 0px;
42 | padding:0px;
43 | width: 13px;
44 | display:inline-block;
45 | vertical-align: middle;
46 | height: 100%;
47 | position: relative;
48 | overflow: hidden;
49 | border-radius: 3px;
50 | margin-left: 8px;
51 | }
52 |
53 | .hue > .hue-container {
54 | border-radius:0px;
55 | overflow:hidden;
56 | height: 100%;
57 | background: linear-gradient(to top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
58 | }
59 |
60 |
61 | .opacity > .opacity-container {
62 | border-radius: 0px;
63 | overflow: hidden;
64 | height: 100%;
65 | }
66 |
67 |
68 | .drag-bar, .drag-bar2 {
69 | border:0px;
70 | background-color: transparent;
71 | border: 2px solid white;
72 | box-shadow: 0 0 1px 0px rgba(0, 0, 0, 1), inset 0 0 1px 0px rgba(0, 0, 0, 1);
73 | width: 10px;
74 | height: 10px;
75 | box-sizing: border-box;
76 | transform: none;
77 | overflow: hidden;
78 | left: 50%;
79 | transform: translateX(-50%) translateY(-50%);
80 | }
81 |
82 | }
83 |
84 | .information {
85 | margin-top: 5px;
86 | }
87 |
88 | }
--------------------------------------------------------------------------------
/src/util/Blender.js:
--------------------------------------------------------------------------------
1 | import separable from './blend/separable'
2 | import nonseparable from './blend/non-separable'
3 | import composite from './blend/composite'
4 |
5 | function num(n) {
6 | if (n < 0) return 0;
7 | return n > 255 ? 255 : n;
8 | }
9 |
10 | function Blender (back, source, blendFunction, blendMode = 'normal', compositeOperation = 'source-over') {
11 |
12 | const compositeFunction = composite[compositeOperation];
13 |
14 | return compositeFunction(back, blendFunction(back, source, blendMode));
15 |
16 | }
17 |
18 | Object.keys(separable).forEach(mode => {
19 | Blender[mode] = function (back, source, compositeOperation = 'source-over') {
20 | return Blender(back, source, separable[mode],mode, compositeOperation)
21 | }
22 | })
23 | Object.keys(nonseparable).forEach(mode => {
24 | Blender[mode] = function (back, source, compositeOperation = 'source-over') {
25 | return Blender(back, source, nonseparable[mode],mode, compositeOperation)
26 | }
27 | })
28 |
29 | export default Blender
--------------------------------------------------------------------------------
/src/util/Color.js:
--------------------------------------------------------------------------------
1 | import formatter from "./functions/formatter";
2 | import math from './functions/math'
3 | import fromRGB from './functions/fromRGB'
4 | import fromCMYK from './functions/fromCMYK'
5 | import fromLAB from './functions/fromLAB'
6 | import fromHSV from './functions/fromHSV'
7 | import fromHSL from './functions/fromHSL'
8 | import fromYCrCb from './functions/fromYCrCb'
9 | import mixin from "./functions/mixin";
10 | import parser from "./functions/parser";
11 | import image from "./functions/image";
12 |
13 |
14 | export default {
15 | ...formatter,
16 | ...math,
17 | ...mixin,
18 | ...parser,
19 | ...fromYCrCb,
20 | ...fromRGB,
21 | ...fromCMYK,
22 | ...fromHSV,
23 | ...fromHSL,
24 | ...fromLAB,
25 | ...image
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/util/Event.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | addEvent (dom, eventName, callback, options) {
4 | if (dom) {
5 | dom.addEventListener(eventName, callback, options);
6 | }
7 | },
8 |
9 | removeEvent(dom, eventName, callback) {
10 | if (dom) {
11 | dom.removeEventListener(eventName, callback);
12 | }
13 | },
14 |
15 | pos(e) {
16 | if (e.touches && e.touches[0]) {
17 | return e.touches[0];
18 | }
19 |
20 | return e;
21 | },
22 |
23 | posXY (e) {
24 | var pos = this.pos(e);
25 | return {
26 | x: pos.pageX,
27 | y: pos.pageY
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/util/GL.js:
--------------------------------------------------------------------------------
1 | import FilterFunctions from './gl/functions'
2 |
3 | import FilterList from './gl/index'
4 |
5 | export default {
6 | ...FilterList,
7 | ...FilterFunctions
8 | }
9 |
--------------------------------------------------------------------------------
/src/util/HueColor.js:
--------------------------------------------------------------------------------
1 | import Color from './Color';
2 |
3 | const hue_color = [
4 | { rgb : '#ff0000', start : .0 },
5 | { rgb : '#ffff00', start : .17 },
6 | { rgb : '#00ff00', start : .33 },
7 | { rgb : '#00ffff', start : .50 },
8 | { rgb : '#0000ff', start : .67 },
9 | { rgb : '#ff00ff', start : .83 },
10 | { rgb : '#ff0000', start : 1 }
11 | ];
12 |
13 | function checkHueColor(p) {
14 | var startColor, endColor;
15 |
16 | for(var i = 0; i < hue_color.length;i++) {
17 | if (hue_color[i].start >= p) {
18 | startColor = hue_color[i-1];
19 | endColor = hue_color[i];
20 | break;
21 | }
22 | }
23 |
24 | if (startColor && endColor) {
25 | return Color.interpolateRGB(startColor, endColor, (p - startColor.start)/(endColor.start - startColor.start));
26 | }
27 |
28 | return hue_color[0].rgb;
29 | }
30 |
31 |
32 | function initHueColors () {
33 | for(var i = 0, len = hue_color.length; i < len; i++) {
34 | var hue = hue_color[i];
35 |
36 | var obj = Color.parse(hue.rgb);
37 |
38 | hue.r = obj.r;
39 | hue.g = obj.g;
40 | hue.b = obj.b;
41 | }
42 | }
43 |
44 | initHueColors();
45 |
46 | export default {
47 | colors : hue_color,
48 | checkHueColor
49 | };
--------------------------------------------------------------------------------
/src/util/ImageFilter.js:
--------------------------------------------------------------------------------
1 | // TODO: worker run
2 | import FilterFunctions from './filter/functions'
3 |
4 | import FilterList from './filter/index'
5 |
6 | export default {
7 | ...FilterList,
8 | ...FilterFunctions
9 | }
10 |
--------------------------------------------------------------------------------
/src/util/State.js:
--------------------------------------------------------------------------------
1 | const DELEGATE_SPLIT = '.';
2 |
3 | export default class State {
4 | constructor (masterObj, settingObj = {}) {
5 |
6 | this.masterObj = masterObj;
7 | this.settingObj = settingObj;
8 | }
9 |
10 | set (key, value, defaultValue = undefined) {
11 | this.settingObj[key] = value || defaultValue;
12 | }
13 |
14 | init (key, ...args) {
15 |
16 | if (!this.has(key)) {
17 |
18 | const arr = key.split(DELEGATE_SPLIT);
19 |
20 | const obj = this.masterObj.refs[arr[0]] || this.masterObj[arr[0]] || this.masterObj;
21 | const method = arr.pop();
22 |
23 | if (obj[method]) {
24 | const value = obj[method].apply(obj, args);
25 |
26 | this.set(key, value);
27 | }
28 |
29 | }
30 | }
31 |
32 | get (key, defaultValue = '') {
33 |
34 | this.init(key, defaultValue);
35 |
36 | return this.settingObj[key] || defaultValue;
37 | }
38 |
39 | has (key) {
40 | return !!this.settingObj[key];
41 | }
42 | }
--------------------------------------------------------------------------------
/src/util/blend/composite.js:
--------------------------------------------------------------------------------
1 | const modes = {
2 | 'clear' : {
3 | alpha () { return 0; },
4 | color () { return 0; }
5 | },
6 | 'copy' : {
7 | alpha (Ab, As) {
8 | return As;
9 | },
10 | color (Ab, As, Cb, Cs) {
11 | return As * Cs;
12 | }
13 | },
14 | 'destination' : {
15 | alpha (Ab, As) {
16 | return Ab;
17 | },
18 | color (Ab, As, Cb, Cs) {
19 | return Ab * Cb;
20 | }
21 | },
22 | 'source-over' : {
23 | alpha (Ab, As) {
24 | return As + Ab * ( 1 - As);
25 | },
26 | color (Ab, As, Cb, Cs) {
27 | return As * Cs + Ab * Cb * (1 - As);
28 | }
29 | },
30 | 'destination-over' : {
31 | alpha (Ab, As) {
32 | return As * (1 - Ab) + Ab;
33 | },
34 | color (Ab, As, Cb, Cs) {
35 | return As * Cs * (1 - Ab) + Ab * Cb;
36 | }
37 | },
38 | 'source-in' : {
39 | alpha (Ab, As) {
40 | return As * Ab;
41 | },
42 | color (Ab, As, Cb, Cs) {
43 | return As * Cs * Ab;
44 | }
45 | },
46 | 'destination-in' : {
47 | alpha (Ab, As) {
48 | return As * Ab;
49 | },
50 | color (Ab, As, Cb, Cs) {
51 | return As * Cb * Ab;
52 | }
53 | },
54 | 'source-out' : {
55 | alpha (Ab, As) {
56 | return As * (1 - Ab);
57 | },
58 | color (Ab, As, Cb, Cs) {
59 | return As * Cs * (1 - Ab);
60 | }
61 | },
62 | 'destination-out' : {
63 | alpha (Ab, As) {
64 | return Ab * (1 - As);
65 | },
66 | color (Ab, As, Cb, Cs) {
67 | return Ab * Cb * (1 - As);
68 | }
69 | },
70 | 'source-atop' : {
71 | alpha (Ab, As) {
72 | return As * Ab + Ab * (1 - As);
73 | },
74 | color (Ab, As, Cb, Cs) {
75 | return As * Cs * Ab + Ab * Cb * (1 - As);
76 | }
77 | },
78 | 'destination-atop' : {
79 | alpha (Ab, As) {
80 | return As * (1 - Ab) + Ab * As;
81 | },
82 | color (Ab, As, Cb, Cs) {
83 | return As * Cs * (1 - Ab) + Ab * Cb * As;
84 | }
85 | },
86 | 'xor' : {
87 | alpha (Ab, As) {
88 | return As * (1 - Ab) + Ab * (1 - As);
89 | },
90 | color (Ab, As, Cb, Cs) {
91 | return As * Cs * (1 - Ab) + Ab * Cb * (1 - As);
92 | }
93 | },
94 | 'lighter' : {
95 | alpha (Ab, As) {
96 | return As + Ab
97 | },
98 | color (Ab, As, Cb, Cs) {
99 | return As * Cs + Ab * Cb;
100 | }
101 | }
102 |
103 |
104 |
105 |
106 | }
107 |
108 | function composite (back, source, mode) {
109 | return {
110 | r : modes[mode].color(back.a, source.a, back.r / 255, source.r / 255) * 255,
111 | g : modes[mode].color(back.a, source.a, back.g / 255, source.g / 255) * 255,
112 | b : modes[mode].color(back.a, source.a, back.b / 255, source.b / 255) * 255,
113 | a : modes[mode].alpha(back.a, source.a)
114 | }
115 | }
116 |
117 | // alias
118 | Object.keys(modes).forEach(mode => {
119 | composite[mode] = function (back, source) {
120 | return composite(back, source, mode);
121 | }
122 | })
123 |
124 | export default composite;
--------------------------------------------------------------------------------
/src/util/blend/non-separable.js:
--------------------------------------------------------------------------------
1 | // refer to https://www.w3.org/TR/compositing-1
2 |
3 | var util = {
4 | lum ( color) {
5 | return 0.3 * color.r + 0.59 * color.g + 0.11 * color.b;
6 | },
7 |
8 | clipColor(c) {
9 | const l = this.lum(c)
10 | const n = this.min(c)
11 | const x = this.max(c)
12 |
13 | let color = Object.assign({}, c);
14 |
15 | if(n < 0) {
16 | color.r = l + (((color.r - l) * l) / (l - n))
17 | color.g = l + (((color.g - l) * l) / (l - n))
18 | color.b = l + (((color.b - l) * l) / (l - n))
19 | }
20 |
21 |
22 | if(x > 1) {
23 | color.r = l + (((color.r - l) * (1 - l)) / (x - l))
24 | color.g = l + (((color.g - l) * (1 - l)) / (x - l))
25 | color.b = l + (((color.b - l) * (1 - l)) / (x - l))
26 | }
27 |
28 | return color;
29 | },
30 | setLum(color, l) {
31 | const d = l - this.lum(color)
32 | const r = color.r + d;
33 | const g = color.g + d;
34 | const b = color.b + d;
35 |
36 | return this.clipColor({r, g, b})
37 | },
38 |
39 | sat (color) {
40 | return this.max(color) - this.min(color)
41 | },
42 |
43 | max (color) {
44 | return Math.max(color.r, color.g, color.b);
45 | },
46 |
47 | min (color) {
48 | return Math.min(color.r, color.g, color.b);
49 | },
50 |
51 | mid (color) {
52 | return (color.r + color.g + color.b) - this.max(color) - this.min(color);
53 | },
54 |
55 | setSat(color, s) {
56 | color.max = this.max(color);
57 | color.min = this.min(color);
58 | color.mid = this.mid(color);
59 |
60 | if(color.max > color.min) {
61 | color.mid = (((color.mid - color.min) * s) / (color.max - color.min))
62 | color.max = s
63 | } else {
64 | color.mid = color.max = 0
65 | }
66 |
67 | color.min = 0
68 |
69 | return color;
70 | }
71 | }
72 |
73 | var modes = {
74 | /* nonseparable mode */
75 | hue (back, source) {
76 | return util.setLum(util.setSat(source, util.sat(back)), util.lum(back))
77 | },
78 |
79 | saturation (back, source) {
80 | return util.setLum(util.setSat(back, util.sat(source)), util.lum(back))
81 | },
82 |
83 | color (back, source) {
84 | return util.setLum(source, util.lum(back));
85 | },
86 |
87 | luminosity (back, source) {
88 | return util.setLum(back, util.lum(source))
89 | }
90 |
91 | }
92 |
93 | function recover (c) {
94 | c.r *= 255;
95 | c.g *= 255;
96 | c.b *= 255;
97 | return c;
98 | }
99 |
100 | function minify (c) {
101 | c.r /= 255;
102 | c.g /= 255;
103 | c.b /= 255;
104 | return c;
105 | }
106 |
107 | function nonseparable (back, source, mode) {
108 | return recover(modes[mode](minify(back), minify(source)));
109 | }
110 |
111 | // alias
112 | Object.keys(modes).forEach(mode => {
113 | nonseparable[mode] = function (back, source) {
114 | return nonseparable(back, source, mode);
115 | }
116 | })
117 |
118 | export default nonseparable;
--------------------------------------------------------------------------------
/src/util/blend/separable.js:
--------------------------------------------------------------------------------
1 | import { sep } from "path";
2 |
3 | // refer to https://www.w3.org/TR/compositing-1
4 | var modes = {
5 | normal ( back, source) {
6 | return source;
7 | },
8 | multiply (back, source) {
9 | return back * source ;
10 | },
11 | screen (back, source) {
12 | return back + source -(back * source);
13 | },
14 | overlay (back, source) {
15 | return this.hardlight(back, source)
16 | },
17 | hardlight (back, source) {
18 | if(source <= 0.5)
19 | return this.multiply(back, 2 * source)
20 | else
21 | return this.screen(back, 2 * source - 1)
22 | },
23 | diffuse (c) {
24 | if(c <= 0.25)
25 | return ((16 * c - 12) * c + 4) * c
26 | else
27 | return Math.sqrt(c)
28 | },
29 |
30 | softlight (back, source) {
31 | if(source <= 0.5)
32 | return back - (1 - 2 * source) * back * (1 - back)
33 | else
34 | return back + (2 * source - 1) * (this.diffuse(back) - back)
35 | },
36 | difference (back, source) {
37 | return Math.abs(back, source);
38 | },
39 | exclusion (back, source) {
40 | return back + source - 2 * back * source
41 | },
42 | darken (back, source) {
43 | return Math.min(back, source)
44 | },
45 | lighten (back, source) {
46 | return Math.max(back, source)
47 | },
48 | colordodge (back, source) {
49 | if(back == 0) return 0;
50 | else if(source == 1) return 1;
51 | else Math.min(1, back / (1 - source))
52 | },
53 | colorburn (back, source) {
54 | if(back == 1) return 1;
55 | else if(source == 0) return 0;
56 | else 1 - Math.min(1, (1 - back) / source)
57 | }
58 | }
59 |
60 | function separable (back, source, mode) {
61 | return {
62 | r : modes[mode](back.r / 255, source.r / 255) * 255,
63 | g : modes[mode](back.g / 255, source.g / 255) * 255,
64 | b : modes[mode](back.b / 255, source.b / 255) * 255,
65 | a : source.a
66 | }
67 | }
68 |
69 | // alias
70 | Object.keys(modes).forEach(mode => {
71 | separable[mode] = function (back, source) {
72 | return separable(back, source, mode);
73 | }
74 | })
75 |
76 | export default separable;
--------------------------------------------------------------------------------
/src/util/filter/image/crop.js:
--------------------------------------------------------------------------------
1 | import { createBitmap } from '../functions'
2 |
3 | export default function crop (startX = 0, startY = 0, width, height) {
4 |
5 | const newBitmap = createBitmap(width * height * 4, width, height)
6 |
7 | return function (bitmap, done, opt = {}) {
8 | for (var y = startY, realY = 0; y < height; y++, realY++) {
9 | for (var x = startX, realX = 0; x < width; x++, realX++) {
10 | newBitmap.pixels[realY * width * realX] = bitmap.pixels[y * width * x]
11 | }
12 | }
13 |
14 | done(newBitmap);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/util/filter/image/flipH.js:
--------------------------------------------------------------------------------
1 | import {swapColor} from '../functions'
2 | export default function flipH () {
3 | return function (bitmap, done, opt = {}) {
4 |
5 | const width = bitmap.width
6 | const height = bitmap.height
7 | const isCenter = width % 2 == 1 ? 1 : 0
8 |
9 | const halfWidth = isCenter ? Math.floor(width / 2) : width / 2 ;
10 |
11 | for (var y = 0; y < height; y++) {
12 | for (var x = 0; x < halfWidth; x++) {
13 |
14 | var startIndex = (y * width + x) << 2
15 | var endIndex = (y * width + (width -1 - x) ) << 2
16 | swapColor(bitmap.pixels, startIndex, endIndex)
17 |
18 | }
19 | }
20 |
21 | done(bitmap);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/util/filter/image/flipV.js:
--------------------------------------------------------------------------------
1 | import {
2 | swapColor
3 | } from '../functions'
4 | export default function flipV () {
5 | return function (bitmap, done, opt = {}) {
6 |
7 | const width = bitmap.width
8 | const height = bitmap.height
9 | const isCenter = height % 2 == 1 ? 1 : 0
10 |
11 | const halfHeight = isCenter ? Math.floor(height / 2) : height / 2 ;
12 |
13 | for (var y = 0; y < halfHeight; y++) {
14 | for (var x = 0; x < width; x++) {
15 |
16 | var startIndex = (y * width + x) << 2
17 | var endIndex = ((height -1 - y) * width + x ) << 2
18 | swapColor(bitmap.pixels, startIndex, endIndex)
19 |
20 | }
21 | }
22 |
23 | done(bitmap);
24 | }
25 | }
--------------------------------------------------------------------------------
/src/util/filter/image/histogram.js:
--------------------------------------------------------------------------------
1 | import { pixel } from '../functions'
2 |
3 | export default function histogram (type = 'gray', points = []) {
4 | var $realPoints = []
5 |
6 | for(var i = 0; i < points.length - 1; i++) {
7 | var sp = points[i]
8 | var ep = points[i+1]
9 |
10 | var distX = ep[0] - sp[0]
11 | var distY = ep[1] - sp[1]
12 |
13 | var rate = distY / distX
14 |
15 | for(var realIndex = 0, start = sp[0]; realIndex < distX; realIndex++, start++ ) {
16 | $realPoints[start] = sp[1] + realIndex * rate
17 | }
18 | }
19 |
20 | $realPoints[255] = 255
21 |
22 | if (type === 'red') {
23 | return pixel(() => {
24 | $r = $realPoints[$r];
25 | }, { }, { $realPoints })
26 | } else if (type === 'green') {
27 | return pixel(() => {
28 | $g = $realPoints[$g];
29 | }, { }, { $realPoints })
30 | } else if (type === 'blue') {
31 | return pixel(() => {
32 | $b = $realPoints[$b];
33 | }, { }, { $realPoints })
34 | } else {
35 | return pixel(() => {
36 |
37 | const l = Color.RGBtoYCrCb($r, $g, $b);
38 | const c = Color.YCrCbtoRGB(clamp($realPoints[clamp(l.y)]), l.cr, l.cb, 0)
39 | $r = c.r
40 | $g = c.g
41 | $b = c.b
42 |
43 | }, { }, { $realPoints })
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/util/filter/image/index.js:
--------------------------------------------------------------------------------
1 | import crop from './crop'
2 | import resize from './resize'
3 | import flipV from './flipV'
4 | import flipH from './flipH'
5 | import rotate from './rotate'
6 | import rotateDegree from './rotateDegree'
7 | import histogram from './histogram'
8 |
9 | export default {
10 | crop,
11 | resize,
12 | flipH,
13 | flipV,
14 | rotate,
15 | rotateDegree,
16 | histogram,
17 | 'rotate-degree' : rotateDegree
18 | }
--------------------------------------------------------------------------------
/src/util/filter/image/resize.js:
--------------------------------------------------------------------------------
1 | import Canvas from '../../Canvas'
2 | // Image manupulate
3 | export default function resize (dstWidth, dstHeight) {
4 | return function (bitmap, done, opt = {}) {
5 |
6 | var c = Canvas.drawPixels(bitmap);
7 | var context = c.getContext('2d');
8 |
9 | c.width = dstWidth;
10 | c.height = dstHeight;
11 |
12 | done({
13 | pixels: new Uint8ClampedArray(context.getImageData(0, 0, dstWidth, dstHeight).data),
14 | width: dstWidth,
15 | height: dstHeight
16 | })
17 | }
18 | }
--------------------------------------------------------------------------------
/src/util/filter/image/rotate.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | packXY,
4 | createBitmap,
5 | fillPixelColor
6 | } from '../functions'
7 |
8 | import rotateDegree from './rotateDegree'
9 |
10 | export default function rotate (degree = 0) {
11 | degree = parseParamNumber(degree)
12 | degree = degree % 360
13 | return function (bitmap, done, opt = {}) {
14 |
15 | if (degree == 0) return bitmap
16 |
17 | if (degree == 90 || degree == 270) {
18 | var newBitmap = createBitmap(bitmap.pixels.length, bitmap.height, bitmap.width)
19 | } else if (degree == 180) {
20 | var newBitmap = createBitmap(bitmap.pixels.length, bitmap.width, bitmap.height)
21 | } else {
22 | return rotateDegree(degree)(bitmap, done, opt)
23 | }
24 | packXY((pixels, i, x, y) => {
25 |
26 | if (degree == 90) {
27 | var endIndex = (x * newBitmap.width + (newBitmap.width -1 - y) ) << 2 // << 2 is equals to (multiply)* 4
28 | } else if (degree == 270) {
29 | var endIndex = ( (newBitmap.height -1 -x) * newBitmap.width + y ) << 2
30 | } else if (degree == 180) {
31 | var endIndex = ((newBitmap.height -1 -y) * newBitmap.width + (newBitmap.width -1 -x)) << 2
32 | }
33 |
34 | fillPixelColor(newBitmap.pixels, endIndex, bitmap.pixels, i)
35 | })(bitmap, function () {
36 | done(newBitmap)
37 | }, opt)
38 | }
39 | }
--------------------------------------------------------------------------------
/src/util/filter/image/rotateDegree.js:
--------------------------------------------------------------------------------
1 | import Matrix from '../../Matrix'
2 | import {
3 | createBitmap,
4 | packXY,
5 | fillPixelColor
6 | } from '../functions'
7 |
8 | export default function rotateDegree(angle, cx = 'center', cy = 'center') {
9 | // const r = F.radian(angle)
10 |
11 | return function (bitmap, done, opt = {}) {
12 | var newBitmap = createBitmap(bitmap.pixels.length, bitmap.width, bitmap.height)
13 | const width = bitmap.width
14 | const height = bitmap.height
15 |
16 | if (cx == 'center') {
17 | cx = Math.floor(width / 2);
18 | }
19 |
20 | if (cy == 'center') {
21 | cy = Math.floor(height/ 2);
22 | }
23 |
24 | const translateMatrix = Matrix.CONSTANT.translate(-cx, -cy)
25 | const translateMatrix2 = Matrix.CONSTANT.translate(cx, cy)
26 | const shear1Matrix = Matrix.CONSTANT.shear1(angle)
27 | const shear2Matrix = Matrix.CONSTANT.shear2(angle)
28 |
29 | packXY((pixels, i, x, y) => {
30 | // console.log(x, y, i)
31 | let arr = Matrix.multiply(translateMatrix, [x, y, 1])
32 |
33 | arr = Matrix.multiply(shear1Matrix, arr).map(Math.round)
34 | arr = Matrix.multiply(shear2Matrix, arr).map(Math.round)
35 | arr = Matrix.multiply(shear1Matrix, arr).map(Math.round)
36 | arr = Matrix.multiply(translateMatrix2, arr)
37 |
38 | const [x1, y1] = arr
39 |
40 | if (x1 < 0) return;
41 | if (y1 < 0) return;
42 | if (x1 > width-1) return;
43 | if (y1 > height-1) return;
44 |
45 | var endIndex = (y1 * width + x1) << 2 // bit 2 shift is * 4
46 |
47 | fillPixelColor(pixels, endIndex, bitmap.pixels, i)
48 |
49 | })(newBitmap, function () {
50 | done(newBitmap)
51 | }, opt)
52 | }
53 | }
--------------------------------------------------------------------------------
/src/util/filter/index.js:
--------------------------------------------------------------------------------
1 | import image from './image/index'
2 | import pixel from './pixel/index'
3 | import matrix from './matrix/index'
4 | import multi from './multi/index'
5 |
6 | export default {
7 | ...image,
8 | ...pixel,
9 | ...matrix,
10 | ...multi
11 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/blur.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution,
3 | parseParamNumber,
4 | createBlurMatrix
5 | } from '../functions'
6 |
7 | export default function (amount = 3, hasAlphaChannel = true) {
8 |
9 | amount = parseParamNumber(amount)
10 |
11 | return convolution(createBlurMatrix(amount))
12 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/emboss.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution
4 | } from '../functions'
5 | /*
6 | * carve, mold, or stamp a design on (a surface) so that it stands out in relief.
7 | *
8 | * @param {Number} amount 0.0 .. 4.0
9 | */
10 | export default function emboss (amount = 4) {
11 | amount = parseParamNumber(amount)
12 | return convolution([
13 | amount * (-2.0), -amount, 0.0,
14 | -amount, 1.0, amount,
15 | 0.0, amount, amount * 2.0,
16 | ]);
17 | }
18 |
--------------------------------------------------------------------------------
/src/util/filter/matrix/gaussian-blur-5x.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function gaussianBlur5x (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | const C = amount / 100;
10 | return convolution(weight([
11 | 1, 4, 6, 4, 1,
12 | 4, 16, 24, 16, 4,
13 | 6, 24, 36, 24, 6,
14 | 4, 16, 24, 16, 4,
15 | 1, 4, 6, 4, 1
16 | ], (1/256) * C ));
17 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/gaussian-blur.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function gaussianBlur (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | const C = amount / 100;
10 |
11 | return convolution(weight([
12 | 1, 2, 1,
13 | 2, 4, 2,
14 | 1, 2, 1
15 | ], (1/16) * C ));
16 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/grayscale2.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function grayscale2 (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | 0.3, 0.3, 0.3, 0, 0,
11 | 0.59, 0.59, 0.59, 0, 0,
12 | 0.11, 0.11, 0.11, 0, 0,
13 | 0, 0, 0, 0, 0,
14 | 0, 0, 0, 0, 0
15 | ], amount / 100));
16 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/index.js:
--------------------------------------------------------------------------------
1 | import blur from './blur'
2 | import emboss from './emboss'
3 | import gaussianBlur from './gaussian-blur'
4 | import gaussianBlur5x from './gaussian-blur-5x'
5 | import grayscale2 from './grayscale2'
6 | import normal from './normal'
7 | import kirschHorizontal from './kirsch-horizontal'
8 | import kirschVertical from './kirsch-vertical'
9 | import laplacian from './laplacian'
10 | import laplacian5x from './laplacian-5x'
11 | import motionBlur from './motion-blur'
12 | import motionBlur2 from './motion-blur-2'
13 | import motionBlur3 from './motion-blur-3'
14 | import negative from './negative'
15 | import sepia2 from './sepia2'
16 | import sharpen from './sharpen'
17 | import sobelHorizontal from './sobel-horizontal'
18 | import sobelVertical from './sobel-vertical'
19 | import stackBlur from './stack-blur'
20 | import transparency from './transparency'
21 | import unsharpMasking from './unsharp-masking'
22 |
23 |
24 | export default {
25 | blur,
26 | emboss,
27 | gaussianBlur,
28 | 'gaussian-blur': gaussianBlur,
29 | gaussianBlur5x,
30 | 'gaussian-blur-5x': gaussianBlur5x,
31 | grayscale2,
32 | normal,
33 | kirschHorizontal,
34 | 'kirsch-horizontal': kirschHorizontal,
35 | kirschVertical,
36 | 'kirsch-vertical': kirschVertical,
37 | laplacian,
38 | laplacian5x,
39 | 'laplacian-5x': laplacian5x,
40 | motionBlur,
41 | 'motion-blur': motionBlur,
42 | motionBlur2,
43 | 'motion-blur-2': motionBlur2,
44 | motionBlur3,
45 | 'motion-blur-3': motionBlur3,
46 | negative,
47 | sepia2,
48 | sharpen,
49 | sobelHorizontal,
50 | 'sobel-horizontal': sobelHorizontal,
51 | sobelVertical,
52 | 'sobel-vertical': sobelVertical,
53 | stackBlur,
54 | 'stack-blur': stackBlur,
55 | transparency,
56 | unsharpMasking,
57 | 'unsharp-masking': unsharpMasking
58 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/kirsch-horizontal.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution
4 | } from '../functions'
5 |
6 | export default function kirschHorizontal (count = 1) {
7 | count = parseParamNumber(count)
8 | return convolution([
9 | 5, 5, 5,
10 | -3, 0, -3,
11 | -3, -3, -3
12 | ]);
13 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/kirsch-vertical.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution
4 | } from '../functions'
5 |
6 | export default function kirschVertical (count = 1) {
7 | count = parseParamNumber(count)
8 | return convolution([
9 | 5, -3, -3,
10 | 5, 0, -3,
11 | 5, -3, -3
12 | ]);
13 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/laplacian-5x.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function laplacian5x (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | -1, -1, -1, -1, -1,
11 | -1, -1, -1, -1, -1,
12 | -1, -1, 24, -1, -1,
13 | -1, -1, -1, -1, -1,
14 | -1, -1, -1, -1, -1
15 | ], amount / 100));
16 | }
17 |
--------------------------------------------------------------------------------
/src/util/filter/matrix/laplacian.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function laplacian (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | -1, -1, -1,
11 | -1, 8, -1,
12 | -1, -1, -1
13 | ], amount / 100));
14 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/motion-blur-2.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution,
3 | weight
4 | } from '../functions'
5 |
6 | export default function motionBlur2 () {
7 | return convolution(weight([
8 | 1, 0, 0, 0, 0, 0, 0, 0, 1,
9 | 0, 1, 0, 0, 0, 0, 0, 1, 0,
10 | 0, 0, 1, 0, 0, 0, 1, 0, 0,
11 | 0, 0, 0, 1, 0, 1, 0, 0, 0,
12 | 0, 0, 0, 0, 1, 0, 0, 0, 0,
13 | 0, 0, 0, 1, 0, 1, 0, 0, 0,
14 | 0, 0, 1, 0, 0, 0, 1, 0, 0,
15 | 0, 1, 0, 0, 0, 0, 0, 1, 0,
16 | 1, 0, 0, 0, 0, 0, 0, 0, 1,
17 | ], 1 / 9));
18 | }
19 |
--------------------------------------------------------------------------------
/src/util/filter/matrix/motion-blur-3.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution,
3 | weight
4 | } from '../functions'
5 |
6 |
7 | export default function motionBlur3 () {
8 | return convolution(weight([
9 | 1, 0, 0, 0, 1, 0, 0, 0, 1,
10 | 0, 1, 0, 0, 1, 0, 0, 1, 0,
11 | 0, 0, 1, 0, 1, 0, 1, 0, 0,
12 | 0, 0, 0, 1, 1, 1, 0, 0, 0,
13 | 1, 1, 1, 1, 1, 1, 1, 1, 1,
14 | 0, 0, 0, 1, 1, 1, 0, 0, 0,
15 | 0, 0, 1, 0, 1, 0, 1, 0, 0,
16 | 0, 1, 0, 0, 1, 0, 0, 1, 0,
17 | 1, 0, 0, 0, 1, 0, 0, 0, 1,
18 | ], 1 / 9));
19 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/motion-blur.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution,
3 | weight
4 | } from '../functions'
5 |
6 | export default function motionBlur () {
7 | return convolution(weight([
8 | 1, 0, 0, 0, 0, 0, 0, 0, 0,
9 | 0, 1, 0, 0, 0, 0, 0, 0, 0,
10 | 0, 0, 1, 0, 0, 0, 0, 0, 0,
11 | 0, 0, 0, 1, 0, 0, 0, 0, 0,
12 | 0, 0, 0, 0, 1, 0, 0, 0, 0,
13 | 0, 0, 0, 0, 0, 1, 0, 0, 0,
14 | 0, 0, 0, 0, 0, 0, 1, 0, 0,
15 | 0, 0, 0, 0, 0, 0, 0, 1, 0,
16 | 0, 0, 0, 0, 0, 0, 0, 0, 1,
17 | ], 1 / 9));
18 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/negative.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function negative (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | -1, 0, 0, 0, 0,
11 | 0, -1, 0, 0, 0,
12 | 0, 0, -1, 0, 0,
13 | 0, 0, 0, 1, 0,
14 | 1, 1, 1, 1, 1
15 | ], amount / 100));
16 | }
17 |
--------------------------------------------------------------------------------
/src/util/filter/matrix/normal.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../functions'
4 |
5 | export default function identity () {
6 | return convolution([
7 | 0, 0, 0,
8 | 0, 1, 0,
9 | 0, 0, 0
10 | ]);
11 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/sepia2.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function sepia2 (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | 0.393, 0.349, 0.272, 0, 0,
11 | 0.769, 0.686, 0.534, 0, 0,
12 | 0.189, 0.168, 0.131, 0, 0,
13 | 0, 0, 0, 0, 0,
14 | 0, 0, 0, 0, 0
15 | ], amount / 100));
16 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/sharpen.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function sharpen (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | 0, -1, 0,
11 | -1, 5, -1,
12 | 0, -1, 0
13 | ], amount / 100));
14 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/sobel-horizontal.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../functions'
4 |
5 | export default function sobelHorizontal () {
6 | return convolution([
7 | -1, -2, -1,
8 | 0, 0, 0,
9 | 1, 2, 1
10 | ]);
11 | }
12 |
--------------------------------------------------------------------------------
/src/util/filter/matrix/sobel-vertical.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../functions'
4 |
5 | export default function sobelVertical () {
6 | return convolution([
7 | -1, 0, 1,
8 | -2, 0, 2,
9 | -1, 0, 1
10 | ]);
11 | }
12 |
--------------------------------------------------------------------------------
/src/util/filter/matrix/stack-blur.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber
3 | } from '../functions'
4 |
5 | import StackBlur from '../StackBlur'
6 |
7 | export default function (radius = 10, hasAlphaChannel = true) {
8 | radius = parseParamNumber(radius)
9 |
10 | return function (bitmap, done, opt = {}) {
11 | let newBitmap = StackBlur(bitmap, radius, hasAlphaChannel )
12 |
13 | done(newBitmap);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/transparency.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function transparency (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | 1, 0, 0, 0, 0,
11 | 0, 1, 0, 0, 0,
12 | 0, 0, 1, 0, 0,
13 | 0, 0, 0, 0.3, 0,
14 | 0, 0, 0, 0, 1,
15 | ], amount / 100));
16 | }
--------------------------------------------------------------------------------
/src/util/filter/matrix/unsharp-masking.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../functions'
6 |
7 | export default function unsharpMasking (amount = 256) {
8 | amount = parseParamNumber(amount)
9 | return convolution(weight([
10 | 1, 4, 6, 4, 1,
11 | 4, 16, 24, 16, 4,
12 | 6, 24, -476, 24, 6,
13 | 4, 16, 24, 16, 4,
14 | 1, 4, 6, 4, 1
15 | ], -1 / amount));
16 | }
--------------------------------------------------------------------------------
/src/util/filter/multi/index.js:
--------------------------------------------------------------------------------
1 | import kirsch from './kirsch'
2 | import sobel from './sobel'
3 | import vintage from './vintage'
4 |
5 | export default {
6 | kirsch,
7 | sobel,
8 | vintage
9 | }
--------------------------------------------------------------------------------
/src/util/filter/multi/kirsch.js:
--------------------------------------------------------------------------------
1 | import {
2 | filter
3 | } from '../functions'
4 |
5 | export default function kirsch () {
6 | return filter('kirsch-horizontal kirsch-vertical');
7 | }
--------------------------------------------------------------------------------
/src/util/filter/multi/sobel.js:
--------------------------------------------------------------------------------
1 | import {
2 | filter
3 | } from '../functions'
4 |
5 | export default function sobel () {
6 | return filter('sobel-horizontal sobel-vertical');
7 | }
--------------------------------------------------------------------------------
/src/util/filter/multi/vintage.js:
--------------------------------------------------------------------------------
1 | import {
2 | filter
3 | } from '../functions'
4 |
5 | export default function vintage () {
6 | return filter(`brightness(15) saturation(-20) gamma(1.8)`)
7 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/bitonal.js:
--------------------------------------------------------------------------------
1 | import Color from '../../Color'
2 | import { pixel } from '../functions'
3 |
4 |
5 | export default function bitonal(darkColor, lightColor, threshold = 100) {
6 | let $darkColor = Color.parse(darkColor);
7 | let $lightColor = Color.parse(lightColor);
8 | let $threshold = threshold
9 |
10 | return pixel(`
11 | const thresholdColor = ( $r + $g + $b ) <= $threshold ? $darkColor : $lightColor
12 |
13 | $r = thresholdColor.r
14 | $g = thresholdColor.g
15 | $b = thresholdColor.b
16 | `, {
17 | $threshold
18 | }, {
19 | $darkColor,
20 | $lightColor
21 | })
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/util/filter/pixel/brightness.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel,
4 | colorMatrix
5 | } from '../functions'
6 |
7 | /*
8 | * @param {Number} amount -100..100 , value < 0 is darken, value > 0 is brighten
9 | */
10 | export default function brightness (amount = 1) {
11 | amount = parseParamNumber(amount)
12 | const $C = Math.floor(255 * (amount / 100));
13 |
14 | return pixel(`
15 | $r += $C
16 | $g += $C
17 | $b += $C
18 | `,{ $C })
19 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/brownie.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function brownie () {
7 |
8 | const $matrix = [
9 | 0.5997023498159715,0.34553243048391263,-0.2708298674538042,0,
10 | -0.037703249837783157,0.8609577587992641,0.15059552388459913,0,
11 | 0.24113635128153335,-0.07441037908422492,0.44972182064877153,0,
12 | 0,0,0,1
13 | ]
14 |
15 | return pixel(`
16 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
17 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
18 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
19 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
20 | `, {
21 | $matrix
22 | })
23 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/clip.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | /**
7 | *
8 | * @param {Number} amount from 0 to 100
9 | */
10 | export default function clip (amount = 0) {
11 | amount = parseParamNumber(amount)
12 | const $C = Math.abs(amount) * 2.55
13 |
14 | return pixel(`
15 |
16 | $r = ($r > 255 - $C) ? 255 : 0
17 | $g = ($g > 255 - $C) ? 255 : 0
18 | $b = ($b > 255 - $C) ? 255 : 0
19 |
20 | `, { $C })
21 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/contrast.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 | /**
6 | *
7 | * @param {*} amount min = -128, max = 128
8 | */
9 | export default function contrast(amount = 0) {
10 | amount = parseParamNumber(amount)
11 | const $C = Math.max((128 + amount) / 128, 0);
12 |
13 | return pixel(`
14 | $r *= $C
15 | $g *= $C
16 | $b *= $C
17 | `, { $C })
18 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/gamma.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function gamma (amount = 1) {
7 | const $C = parseParamNumber(amount)
8 | return pixel(`
9 | $r = Math.pow($r / 255, $C) * 255
10 | $g = Math.pow($g / 255, $C) * 255
11 | $b = Math.pow($b / 255, $C) * 255
12 | `, { $C })
13 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/gradient.js:
--------------------------------------------------------------------------------
1 | import Color from '../../Color'
2 | import {
3 | // clamp,
4 | pixel
5 | } from '../functions'
6 | /**
7 | * F.gradient('red', 'blue', 'yellow', 'white', 10)
8 | * F.gradient('red, blue, yellow, white, 10')
9 | */
10 | export default function gradient () {
11 | // 전체 매개변수 기준으로 파싱
12 | // 색이 아닌 것 기준으로 scale 변수로 인식
13 |
14 | let params = [...arguments];
15 |
16 | if (params.length === 1 && typeof params[0] === 'string') {
17 | params = Color.convertMatchesArray(params[0])
18 | }
19 |
20 | params = params.map(arg => {
21 | const res = Color.matches(arg)
22 |
23 | if (!res.length) {
24 | return { type: 'scale', value : arg }
25 | }
26 |
27 | return { type: 'param', value : arg }
28 | })
29 |
30 | let $scale = params.filter(it => { return it.type == 'scale' })[0]
31 | $scale = $scale ? +$scale.value : 256
32 |
33 | params = params.filter(it => { return it.type == 'param' }).map( it => {
34 | return it.value
35 | }).join(',')
36 |
37 | let $colors = Color.gradient(params, $scale).map(c => {
38 | const { r, g, b, a } = Color.parse(c)
39 | return {r, g, b, a}
40 | })
41 |
42 | return pixel(`
43 | const colorIndex = clamp(Math.ceil($r * 0.2126 + $g * 0.7152 + $b * 0.0722))
44 | const newColorIndex = clamp(Math.floor(colorIndex * ($scale / 256)))
45 | const color = $colors[newColorIndex]
46 |
47 | $r = color.r
48 | $g = color.g
49 | $b = color.b
50 | $a = clamp(Math.floor(color.a * 256))
51 | `, { }, { $colors, $scale })
52 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/grayscale.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function grayscale (amount) {
7 | amount = parseParamNumber(amount)
8 | let C = amount / 100;
9 |
10 | if (C > 1) C = 1;
11 |
12 | const $matrix = [
13 | (0.2126 + 0.7874 * (1 - C)), (0.7152 - 0.7152 * (1 - C)), (0.0722 - 0.0722 * (1 - C)), 0,
14 | (0.2126 - 0.2126 * (1 - C)), (0.7152 + 0.2848 * (1 - C)), (0.0722 - 0.0722 * (1 - C)), 0,
15 | (0.2126 - 0.2126 * (1 - C)), (0.7152 - 0.7152 * (1 - C)), (0.0722 + 0.9278 * (1 - C)), 0,
16 | 0, 0, 0, 1
17 | ]
18 |
19 | return pixel(/*javascript*/`
20 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
21 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
22 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
23 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
24 | `, {
25 | $matrix
26 | });
27 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/hue.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | /*
7 | * @param {Number} amount 0..360
8 | */
9 | export default function hue (amount = 360) {
10 | const $C = parseParamNumber(amount)
11 | return pixel(`
12 | var hsv = Color.RGBtoHSV($r, $g, $b);
13 |
14 | // 0 ~ 360
15 | var h = hsv.h;
16 | h += Math.abs($C)
17 | h = h % 360
18 | hsv.h = h
19 |
20 | var rgb = Color.HSVtoRGB(hsv);
21 |
22 | $r = rgb.r
23 | $g = rgb.g
24 | $b = rgb.b
25 | `, {
26 | $C
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/src/util/filter/pixel/index.js:
--------------------------------------------------------------------------------
1 |
2 | import bitonal from './bitonal'
3 | import brightness from './brightness'
4 | import brownie from './brownie'
5 | import clip from './clip'
6 | import contrast from './contrast'
7 | import gamma from './gamma'
8 | import gradient from './gradient'
9 | import grayscale from './grayscale'
10 | import hue from './hue'
11 | import invert from './invert'
12 | import kodachrome from './kodachrome'
13 | import matrix from './matrix'
14 | import noise from './noise'
15 | import opacity from './opacity'
16 | import polaroid from './polaroid'
17 | import saturation from './saturation'
18 | import sepia from './sepia'
19 | import shade from './shade'
20 | import shift from './shift'
21 | import solarize from './solarize'
22 | import technicolor from './technicolor'
23 | import threshold from './threshold'
24 | import thresholdColor from './threshold-color'
25 | import tint from './tint'
26 |
27 | export default {
28 | bitonal,
29 | brightness,
30 | brownie,
31 | clip,
32 | contrast,
33 | gamma,
34 | gradient,
35 | grayscale,
36 | hue,
37 | invert,
38 | kodachrome,
39 | matrix,
40 | noise,
41 | opacity,
42 | polaroid,
43 | saturation,
44 | sepia,
45 | shade,
46 | shift,
47 | solarize,
48 | technicolor,
49 | threshold,
50 | 'threshold-color': thresholdColor,
51 | tint
52 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/invert.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 | export default function invert (amount = 100) {
6 | amount = parseParamNumber(amount)
7 | const $C = amount / 100;
8 |
9 | return pixel(`
10 | $r = (255 - $r) * $C
11 | $g = (255 - $g) * $C
12 | $b = (255 - $b) * $C
13 | `, {
14 | $C
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/src/util/filter/pixel/kodachrome.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function kodachrome () {
7 |
8 | const $matrix = [
9 | 1.1285582396593525,-0.3967382283601348,-0.03992559172921793,0,
10 | -0.16404339962244616,1.0835251566291304,-0.05498805115633132,0,
11 | -0.16786010706155763,-0.5603416277695248,1.6014850761964943,0,
12 | 0,0,0,1
13 | ]
14 |
15 | return pixel(`
16 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
17 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
18 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
19 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
20 | `, {
21 | $matrix
22 | })
23 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/matrix.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function matrix (
7 | $a = 0, $b = 0, $c = 0, $d = 0,
8 | $e = 0, $f = 0, $g = 0, $h = 0,
9 | $i = 0, $j = 0, $k = 0, $l = 0,
10 | $m = 0, $n = 0, $o = 0, $p = 0
11 | ) {
12 |
13 | const $matrix = [
14 | $a, $b, $c, $d,
15 | $e, $f, $g, $h,
16 | $i, $j, $k, $l,
17 | $m, $n, $o, $p
18 | ]
19 |
20 | return pixel(`
21 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
22 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
23 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
24 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
25 | `, {
26 | $matrix
27 | })
28 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/noise.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | /**
7 | *
8 | * @param {Number} amount 1..100
9 | */
10 | export default function noise (amount = 1) {
11 | const $C = parseParamNumber(amount)
12 | return pixel(`
13 | const C = Math.abs($C) * 5
14 | const min = -C
15 | const max = C
16 | const noiseValue = Math.round(min + (Math.random() * (max - min)))
17 |
18 | $r += noiseValue
19 | $g += noiseValue
20 | $b += noiseValue
21 | `, {
22 | $C
23 | })
24 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/opacity.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 |
7 | export default function opacity (amount = 100) {
8 | amount = parseParamNumber(amount)
9 | const $C = amount / 100;
10 |
11 | return pixel(`
12 | $a *= $C
13 | `, { $C })
14 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/polaroid.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function polaroid () {
7 |
8 | const $matrix = [
9 | 1.438,-0.062,-0.062,0,
10 | -0.122,1.378,-0.122,0,
11 | -0.016,-0.016,1.483,0,
12 | 0,0,0,1
13 | ]
14 |
15 | return pixel(`
16 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
17 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
18 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
19 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
20 | `, {
21 | $matrix
22 | })
23 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/saturation.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | /*
7 | * @param {Number} amount -100..100
8 | */
9 | export default function saturation (amount = 100) {
10 | amount = parseParamNumber(amount)
11 | const C = amount / 100
12 | const L = 1 - Math.abs(C);
13 |
14 | const $matrix = [
15 | L, 0, 0, 0,
16 | 0, L, 0, 0,
17 | 0, 0, L, 0,
18 | 0, 0, 0, L
19 | ]
20 |
21 | return pixel(`
22 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
23 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
24 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
25 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
26 | `, {
27 | $matrix
28 | })
29 |
30 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/sepia.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | /*
7 | * @param {Number} amount 0..1
8 | */
9 | export default function sepia (amount = 1) {
10 | let C = parseParamNumber(amount);
11 | if (C > 1) C = 1;
12 |
13 | const $matrix = [
14 | (0.393 + 0.607 * (1 - C)), (0.769 - 0.769 * (1 - C)), (0.189 - 0.189 * (1 - C)), 0,
15 | (0.349 - 0.349 * (1 - C)), (0.686 + 0.314 * (1 - C)), (0.168 - 0.168 * (1 - C)), 0,
16 | (0.272 - 0.272 * (1 - C)), (0.534 - 0.534 * (1 - C)), (0.131 + 0.869 * (1 - C)), 0,
17 | 0, 0, 0, 1
18 | ]
19 |
20 | return pixel(`
21 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
22 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
23 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
24 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
25 | `, {
26 | $matrix
27 | })
28 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/shade.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function shade(redValue = 1, greenValue = 1, blueValue = 1) {
7 | const $redValue = parseParamNumber(redValue)
8 | const $greenValue = parseParamNumber(greenValue)
9 | const $blueValue = parseParamNumber(blueValue)
10 |
11 | return pixel(`
12 | $r *= $redValue
13 | $g *= $greenValue
14 | $b *= $blueValue
15 | `, {
16 | $redValue,
17 | $greenValue,
18 | $blueValue
19 | })
20 |
21 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/shift.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function shift () {
7 |
8 | const $matrix = [
9 | 1.438,-0.062,-0.062,0,
10 | -0.122,1.378,-0.122,0,
11 | -0.016,-0.016,1.483,0,
12 | 0,0,0,1
13 | ]
14 |
15 | return pixel(`
16 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
17 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
18 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
19 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
20 | `, {
21 | $matrix
22 | })
23 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/solarize.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 | /**
6 | * change the relative darkness of (a part of an image) by overexposure to light.
7 | * @param {*} r
8 | * @param {*} g
9 | * @param {*} b
10 | */
11 | export default function solarize (redValue, greenValue, blueValue) {
12 | const $redValue = parseParamNumber(redValue)
13 | const $greenValue = parseParamNumber(greenValue)
14 | const $blueValue = parseParamNumber(blueValue)
15 | return pixel(`
16 | $r = ($r < $redValue) ? 255 - $r: $r
17 | $g = ($g < $greenValue) ? 255 - $g: $g
18 | $b = ($b < $blueValue) ? 255 - $b: $b
19 | `, {
20 | $redValue, $greenValue, $blueValue
21 | })
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/util/filter/pixel/technicolor.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 | export default function technicolor () {
7 |
8 | const $matrix = [
9 | 1.9125277891456083,-0.8545344976951645,-0.09155508482755585,0,
10 | -0.3087833385928097,1.7658908555458428,-0.10601743074722245,0,
11 | -0.231103377548616,-0.7501899197440212,1.847597816108189,0,
12 | 0,0,0,1
13 | ]
14 |
15 | return pixel(`
16 | $r = $matrix[0] * $r + $matrix[1] * $g + $matrix[2] * $b + $matrix[3] * $a
17 | $g = $matrix[4] * $r + $matrix[5] * $g + $matrix[6] * $b + $matrix[7] * $a
18 | $b = $matrix[8] * $r + $matrix[9] * $g + $matrix[10] * $b + $matrix[11] * $a
19 | $a = $matrix[12] * $r + $matrix[13] * $g + $matrix[14] * $b + $matrix[15] * $a
20 | `, {
21 | $matrix
22 | })
23 | }
--------------------------------------------------------------------------------
/src/util/filter/pixel/threshold-color.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | pixel
4 | } from '../functions'
5 |
6 |
7 | export default function thresholdColor (scale = 200, amount = 100, hasColor = true) {
8 | const $scale = parseParamNumber(scale)
9 | amount = parseParamNumber(amount)
10 | const $C = amount / 100;
11 | const $hasColor = hasColor
12 |
13 | return pixel(`
14 | // refer to Color.brightness
15 | const v = ($C * Math.ceil($r * 0.2126 + $g * 0.7152 + $b * 0.0722) ) >= $scale ? 255 : 0;
16 |
17 | if ($hasColor) {
18 |
19 | if (v == 0) {
20 | $r = 0
21 | $g = 0
22 | $b = 0
23 | }
24 |
25 | } else {
26 | const value = Math.round(v)
27 | $r = value
28 | $g = value
29 | $b = value
30 | }
31 |
32 | `, {
33 | $C, $scale, $hasColor
34 | })
35 | }
36 |
--------------------------------------------------------------------------------
/src/util/filter/pixel/threshold.js:
--------------------------------------------------------------------------------
1 | import thresholdColor from './threshold-color'
2 | /*
3 | * @param {Number} amount 0..100
4 | */
5 | export default function threshold (scale = 200, amount = 100) {
6 | return thresholdColor(scale, amount, false)
7 | }
8 |
--------------------------------------------------------------------------------
/src/util/filter/pixel/tint.js:
--------------------------------------------------------------------------------
1 | import { pixel, parseParamNumber } from "../functions";
2 |
3 |
4 | export default function (redTint = 1, greenTint = 1, blueTint = 1) {
5 | const $redTint = parseParamNumber(redTint)
6 | const $greenTint = parseParamNumber(greenTint)
7 | const $blueTint = parseParamNumber(blueTint)
8 | return pixel(`
9 |
10 | $r += (255 - $r) * $redTint
11 | $g += (255 - $g) * $greenTint
12 | $b += (255 - $b) * $blueTint
13 |
14 | `, {
15 | $redTint,
16 | $greenTint,
17 | $blueTint
18 | })
19 |
20 | }
--------------------------------------------------------------------------------
/src/util/functions/formatter.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @method format
4 | *
5 | * convert color to format string
6 | *
7 | * // hex
8 | * color.format({ r : 255, g : 255, b : 255, a: 1 }, 'hex') // #FFFFFFFF
9 | *
10 | * // rgb
11 | * color.format({ r : 255, g : 255, b : 255 }, 'rgb') // rgba(255, 255, 255, 0.5);
12 | *
13 | * // rgba
14 | * color.format({ r : 255, g : 255, b : 255, a : 0.5 }, 'rgb') // rgba(255, 255, 255, 0.5);
15 | *
16 | * @param {Object} obj obj has r, g, b and a attributes
17 | * @param {"hex"/"rgb"} type format string type
18 | * @returns {*}
19 | */
20 | export function format(obj, type, defaultColor = 'rgba(0, 0, 0, 0)') {
21 |
22 | if (Array.isArray(obj)) {
23 | obj = { r: obj[0], g: obj[1], b: obj[2], a: obj[3] }
24 | }
25 |
26 | if (type == 'hex') {
27 | return hex(obj);
28 | } else if (type == 'rgb') {
29 | return rgb(obj, defaultColor);
30 | } else if (type == 'hsl') {
31 | return hsl(obj);
32 | }
33 |
34 | return obj;
35 | }
36 |
37 | export function hex(obj) {
38 | if (Array.isArray(obj)) {
39 | obj = { r: obj[0], g: obj[1], b: obj[2], a: obj[3] }
40 | }
41 |
42 | var r = obj.r.toString(16);
43 | if (obj.r < 16) r = "0" + r;
44 |
45 | var g = obj.g.toString(16);
46 | if (obj.g < 16) g = "0" + g;
47 |
48 | var b = obj.b.toString(16);
49 | if (obj.b < 16) b = "0" + b;
50 |
51 |
52 | var alphaValue = ''
53 | if (obj.a < 1) {
54 | var alpha = Math.floor(obj.a * 255)
55 | var alphaValue = alpha.toString(16);
56 | if (alpha < 16) alphaValue = "0" + alphaValue;
57 | }
58 |
59 | return `#${r}${g}${b}${alphaValue}`;
60 | }
61 |
62 | export function rgb (obj, defaultColor = 'rgba(0, 0, 0, 0)') {
63 | if (Array.isArray(obj)) {
64 | obj = { r: obj[0], g: obj[1], b: obj[2], a: obj[3] }
65 | }
66 |
67 | if (typeof obj == 'undefined') {
68 | return undefined;
69 | }
70 |
71 | if (obj.a == 1 || typeof obj.a == 'undefined') {
72 | if (isNaN(obj.r)) {
73 | return defaultColor;
74 | }
75 | return `rgb(${obj.r},${obj.g},${obj.b})`;
76 | } else {
77 | return `rgba(${obj.r},${obj.g},${obj.b},${obj.a})`;
78 | }
79 | }
80 |
81 | export function hsl (obj) {
82 | if (Array.isArray(obj)) {
83 | obj = { r: obj[0], g: obj[1], b: obj[2], a: obj[3] }
84 | }
85 |
86 | if (obj.a == 1 || typeof obj.a == 'undefined') {
87 | return `hsl(${obj.h},${obj.s}%,${obj.l}%)`;
88 | } else {
89 | return `hsla(${obj.h},${obj.s}%,${obj.l}%,${obj.a})`;
90 | }
91 |
92 | }
93 |
94 | export default {
95 | format,
96 | rgb,
97 | hsl,
98 | hex
99 | };
--------------------------------------------------------------------------------
/src/util/functions/fromCMYK.js:
--------------------------------------------------------------------------------
1 |
2 | export function CMYKtoRGB(c, m, y, k) {
3 |
4 | if (arguments.length == 1) {
5 | var { c, m, y, k } = arguments[0];
6 | }
7 |
8 | const R = 255 * (1 - c) * (1 - k);
9 | const G = 255 * (1 - m) * (1 - k);
10 | const B = 255 * (1 - y) * (1 - k);
11 |
12 | return { r: R, g: G, b: B }
13 | }
14 |
15 | export default {
16 | CMYKtoRGB
17 | }
--------------------------------------------------------------------------------
/src/util/functions/fromHSL.js:
--------------------------------------------------------------------------------
1 | import { RGBtoHSV } from './fromRGB'
2 | import { round } from './math'
3 |
4 | export function HUEtoRGB(p, q, t) {
5 | if (t < 0) t += 1;
6 | if (t > 1) t -= 1;
7 | if (t < 1 / 6) return p + (q - p) * 6 * t;
8 | if (t < 1 / 2) return q;
9 | if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
10 | return p;
11 | }
12 |
13 | export function HSLtoHSV(h, s, l) {
14 |
15 | if (arguments.length == 1) {
16 | var { h, s, l } = arguments[0];
17 | }
18 | const rgb = HSLtoRGB(h, s, l);
19 |
20 | return RGBtoHSV(rgb.r, rgb.g, rgb.b);
21 | }
22 |
23 | export function HSLtoRGB(h, s, l) {
24 |
25 | if (arguments.length == 1) {
26 | var { h, s, l } = arguments[0];
27 | }
28 |
29 | var r, g, b;
30 |
31 | h /= 360;
32 | s /= 100;
33 | l /= 100;
34 |
35 | if (s == 0) {
36 | r = g = b = l; // achromatic
37 | } else {
38 | var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
39 | var p = 2 * l - q;
40 | r = HUEtoRGB(p, q, h + 1 / 3);
41 | g = HUEtoRGB(p, q, h);
42 | b = HUEtoRGB(p, q, h - 1 / 3);
43 | }
44 |
45 | return { r: round(r * 255), g: round(g * 255), b: round(b * 255) };
46 | }
47 |
48 | export default {
49 | HUEtoRGB,
50 | HSLtoHSV,
51 | HSLtoRGB
52 | }
--------------------------------------------------------------------------------
/src/util/functions/fromHSV.js:
--------------------------------------------------------------------------------
1 | import { round } from './math'
2 | import { RGBtoHSL } from './fromRGB'
3 |
4 | /**
5 | * @method HSVtoRGB
6 | *
7 | * convert hsv to rgb
8 | *
9 | * color.HSVtoRGB(0,0,1) === #FFFFF === { r : 255, g : 0, b : 0 }
10 | *
11 | * @param {Number} H hue color number (min : 0, max : 360)
12 | * @param {Number} S Saturation number (min : 0, max : 1)
13 | * @param {Number} V Value number (min : 0, max : 1 )
14 | * @returns {Object}
15 | */
16 | export function HSVtoRGB(h, s, v) {
17 |
18 | if (arguments.length == 1) {
19 | var { h, s, v } = arguments[0];
20 | }
21 |
22 | var H = h;
23 | var S = s;
24 | var V = v;
25 |
26 | if (H >= 360) {
27 | H = 0;
28 | }
29 |
30 | const C = S * V;
31 | const X = C * (1 - Math.abs((H / 60) % 2 - 1));
32 | const m = V - C;
33 |
34 | let temp = [];
35 |
36 | if (0 <= H && H < 60) { temp = [C, X, 0]; }
37 | else if (60 <= H && H < 120) { temp = [X, C, 0]; }
38 | else if (120 <= H && H < 180) { temp = [0, C, X]; }
39 | else if (180 <= H && H < 240) { temp = [0, X, C]; }
40 | else if (240 <= H && H < 300) { temp = [X, 0, C]; }
41 | else if (300 <= H && H < 360) { temp = [C, 0, X]; }
42 |
43 | return {
44 | r: round((temp[0] + m) * 255),
45 | g: round((temp[1] + m) * 255),
46 | b: round((temp[2] + m) * 255)
47 | };
48 | }
49 |
50 | export function HSVtoHSL(h, s, v) {
51 |
52 | if (arguments.length == 1) {
53 | var { h, s, v } = arguments[0];
54 | }
55 |
56 | const rgb = HSVtoRGB(h, s, v);
57 |
58 | return RGBtoHSL(rgb.r, rgb.g, rgb.b);
59 | }
60 |
61 | export default {
62 | HSVtoHSL,
63 | HSVtoRGB
64 | }
--------------------------------------------------------------------------------
/src/util/functions/fromLAB.js:
--------------------------------------------------------------------------------
1 | import { round } from './math'
2 |
3 | export function ReverseXyz(n) {
4 | return (Math.pow(n, 3) > 0.008856) ? Math.pow(n, 3) : (n - 16 / 116) / 7.787;
5 | }
6 |
7 | export function ReverseRGB(n) {
8 | return (n > 0.0031308) ? 1.055 * (Math.pow(n, (1 / 2.4))) - 0.055 : 12.92 * n;
9 | }
10 |
11 | export function XYZtoRGB(x, y, z) {
12 | if (arguments.length == 1) {
13 | var { x, y, z } = arguments[0];
14 | }
15 | //X, Y and Z input refer to a D65/2° standard illuminant.
16 | //sR, sG and sB (standard RGB) output range = 0 ÷ 255
17 |
18 | let X = x / 100.0
19 | let Y = y / 100.0
20 | let Z = z / 100.0
21 |
22 | let R = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
23 | let G = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
24 | let B = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
25 |
26 | R = ReverseRGB(R);
27 | G = ReverseRGB(G);
28 | B = ReverseRGB(B);
29 |
30 | const r = round(R * 255);
31 | const g = round(G * 255);
32 | const b = round(B * 255);
33 |
34 | return { r, g, b };
35 | }
36 |
37 | export function LABtoXYZ(l, a, b) {
38 | if (arguments.length == 1) {
39 | var { l, a, b } = arguments[0];
40 | }
41 | //Reference-X, Y and Z refer to specific illuminants and observers.
42 | //Common reference values are available below in this same page.
43 |
44 | let Y = (l + 16) / 116
45 | let X = a / 500 + Y
46 | let Z = Y - b / 200
47 |
48 | Y = ReverseXyz(Y);
49 | X = ReverseXyz(X);
50 | Z = ReverseXyz(Z);
51 |
52 | const x = X * 95.047
53 | const y = Y * 100.000
54 | const z = Z * 108.883
55 |
56 | return { x, y, z };
57 | }
58 |
59 | export function PivotXyz(n) {
60 | return (n > 0.008856) ? Math.pow(n, (1 / 3)) : (7.787 * n + 16) / 116;
61 | }
62 |
63 |
64 | export function XYZtoLAB(x, y, z) {
65 | if (arguments.length == 1) {
66 | var { x, y, z } = arguments[0];
67 | }
68 |
69 | //Reference-X, Y and Z refer to specific illuminants and observers.
70 | //Common reference values are available below in this same page.
71 | // Observer= 2°, Illuminant= D65
72 |
73 | let X = x / 95.047;
74 | let Y = y / 100.00;
75 | let Z = z / 108.883;
76 |
77 | X = PivotXyz(X);
78 | Y = PivotXyz(Y);
79 | Z = PivotXyz(Z);
80 |
81 | const l = (116 * Y) - 16;
82 | const a = 500 * (X - Y);
83 | const b = 200 * (Y - Z);
84 |
85 | return { l, a, b };
86 | }
87 |
88 | export function LABtoRGB(l, a, b) {
89 | if (arguments.length == 1) {
90 | var { l, a, b } = arguments[0];
91 | }
92 | return XYZtoRGB(LABtoXYZ(l, a, b));
93 | }
94 |
95 | export default {
96 | XYZtoRGB,
97 | LABtoRGB,
98 | LABtoXYZ
99 | }
--------------------------------------------------------------------------------
/src/util/functions/fromYCrCb.js:
--------------------------------------------------------------------------------
1 | export function YCrCbtoRGB(y, cr, cb, bit) {
2 |
3 | if (arguments.length == 1) {
4 | var { y, cr, cb, bit } = arguments[0];
5 | bit = bit || 0;
6 | }
7 | const R = y + 1.402 * (cr - bit);
8 | const G = y - 0.344 * (cb - bit) - 0.714 * (cr - bit);
9 | const B = y + 1.772 * (cb - bit);
10 |
11 | return { r: Math.ceil(R), g: Math.ceil(G), b: Math.ceil(B) }
12 | }
13 |
14 | export default {
15 | YCrCbtoRGB
16 | }
--------------------------------------------------------------------------------
/src/util/functions/math.js:
--------------------------------------------------------------------------------
1 | export function round (n, k) {
2 | k = typeof k == 'undefined' ? 1 : k;
3 | return Math.round(n * k) / k;
4 | }
5 |
6 |
7 | export function degreeToRadian (angle) {
8 | return angle * Math.PI / 180;
9 | }
10 |
11 | /**
12 | *
13 | * convert radian to degree
14 | *
15 | * @param {*} radian
16 | * @returns {Number} 0..360
17 | */
18 | export function radianToDegree(radian) {
19 | var angle = radian * 180 / Math.PI;
20 |
21 |
22 | if (angle < 0) { // 각도가 0보다 작으면 360 에서 반전시킨다.
23 | angle = 360 + angle
24 | }
25 |
26 | return angle;
27 | }
28 |
29 |
30 | export function getXInCircle (angle, radius, centerX = 0) {
31 | return centerX + radius * Math.cos(degreeToRadian (angle))
32 | }
33 |
34 | export function getYInCircle (angle, radius, centerY = 0) {
35 | return centerY + radius * Math.sin(degreeToRadian(angle))
36 | }
37 |
38 | export function getXYInCircle (angle, radius, centerX = 0, centerY = 0) {
39 | return {
40 | x : getXInCircle(angle, radius, centerX),
41 | y : getYInCircle(angle, radius, centerY)
42 | }
43 | }
44 |
45 | export function caculateAngle (rx, ry) {
46 | return radianToDegree(Math.atan2(ry, rx))
47 | }
48 |
49 | export default {
50 | round,
51 | radianToDegree,
52 | degreeToRadian,
53 | getXInCircle,
54 | getYInCircle,
55 | caculateAngle
56 | }
--------------------------------------------------------------------------------
/src/util/functions/support.js:
--------------------------------------------------------------------------------
1 | function isSupported(api, apiParent) {
2 | return (api in apiParent);
3 | }
4 |
5 | export const enableEyeDropper = isSupported('EyeDropper', window);
--------------------------------------------------------------------------------
/src/util/gl/filter/index.js:
--------------------------------------------------------------------------------
1 | import matrix from './matrix/index'
2 | import pixel from './pixel/index'
3 | import multi from './multi/index'
4 |
5 | export default {
6 | ...matrix,
7 | ...pixel,
8 | ...multi
9 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/blur.js:
--------------------------------------------------------------------------------
1 | import { convolution } from '../util'
2 |
3 | export default function () {
4 | return convolution([
5 | 1, 1, 1,
6 | 1, 1, 1,
7 | 1, 1, 1
8 | ])
9 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/emboss.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution
4 | } from '../util'
5 | /*
6 | * carve, mold, or stamp a design on (a surface) so that it stands out in relief.
7 | *
8 | * @param {Number} amount 0.0 .. 4.0
9 | */
10 | export default function emboss (amount = 4) {
11 | amount = parseParamNumber(amount)
12 | return convolution([
13 | amount * (-2.0), -amount, 0.0,
14 | -amount, 1.0, amount,
15 | 0.0, amount, amount * 2.0,
16 | ]);
17 | }
18 |
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/gaussian-blur-5x.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../util'
6 |
7 | export default function gaussianBlur5x () {
8 | return convolution([
9 | 1, 4, 6, 4, 1,
10 | 4, 16, 24, 16, 4,
11 | 6, 24, 36, 24, 6,
12 | 4, 16, 24, 16, 4,
13 | 1, 4, 6, 4, 1
14 | ]);
15 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/gaussian-blur.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | convolution,
4 | weight
5 | } from '../util'
6 |
7 | /**
8 | *
9 | * @param {Number} amount 0..1
10 | */
11 | export default function gaussianBlur (amount = 1) {
12 | const C = parseParamNumber(amount) * (1/16)
13 |
14 | return convolution(weight([
15 | 1, 2, 1,
16 | 2, 4, 2,
17 | 1, 2, 1
18 | ], C ));
19 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/grayscale2.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function grayscale2 () {
6 | return convolution([
7 | 0.3, 0.3, 0.3, 0, 0,
8 | 0.59, 0.59, 0.59, 0, 0,
9 | 0.11, 0.11, 0.11, 0, 0,
10 | 0, 0, 0, 0, 0,
11 | 0, 0, 0, 0, 0
12 | ]);
13 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/index.js:
--------------------------------------------------------------------------------
1 | import blur from './blur'
2 | import normal from './normal'
3 | import emboss from './emboss'
4 | import gaussianBlur from './gaussian-blur'
5 | import gaussianBlur5x from './gaussian-blur-5x'
6 | import grayscale2 from './grayscale2'
7 | import kirschHorizontal from './kirsch-horizontal'
8 | import kirschVertical from './kirsch-vertical'
9 | import laplacian from './laplacian'
10 | import laplacian5x from './laplacian-5x'
11 | import motionBlur from './motion-blur'
12 | import motionBlur2 from './motion-blur-2'
13 | import motionBlur3 from './motion-blur-3'
14 | import negative from './negative'
15 | import sepia2 from './sepia2'
16 | import sharpen from './sharpen'
17 | import sobelHorizontal from './sobel-horizontal'
18 | import sobelVertical from './sobel-vertical'
19 | import transparency from './transparency'
20 | import unsharpMasking from './unsharp-masking'
21 |
22 |
23 | export default {
24 | blur,
25 | normal,
26 | emboss,
27 | gaussianBlur,
28 | 'gaussian-blur': gaussianBlur,
29 | gaussianBlur5x,
30 | 'gaussian-blur-5x': gaussianBlur5x,
31 | grayscale2,
32 | kirschHorizontal,
33 | 'kirsch-horizontal': kirschHorizontal,
34 | kirschVertical,
35 | 'kirsch-vertical': kirschVertical,
36 | laplacian,
37 | laplacian5x,
38 | 'laplacian-5x': laplacian5x,
39 | motionBlur,
40 | 'motion-blur': motionBlur,
41 | motionBlur2,
42 | 'motion-blur-2': motionBlur2,
43 | motionBlur3,
44 | 'motion-blur-3': motionBlur3,
45 | negative,
46 | sepia2,
47 | sharpen,
48 | sobelHorizontal,
49 | 'sobel-horizontal': sobelHorizontal,
50 | sobelVertical,
51 | 'sobel-vertical': sobelVertical,
52 | transparency,
53 | unsharpMasking,
54 | 'unsharp-masking': unsharpMasking
55 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/kirsch-horizontal.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function kirschHorizontal () {
6 | return convolution([
7 | 5, 5, 5,
8 | -3, 0, -3,
9 | -3, -3, -3
10 | ]);
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/kirsch-vertical.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function kirschVertical () {
6 | return convolution([
7 | 5, -3, -3,
8 | 5, 0, -3,
9 | 5, -3, -3
10 | ]);
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/laplacian-5x.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function laplacian5x () {
6 | return convolution([
7 | -1, -1, -1, -1, -1,
8 | -1, -1, -1, -1, -1,
9 | -1, -1, 24, -1, -1,
10 | -1, -1, -1, -1, -1,
11 | -1, -1, -1, -1, -1
12 | ]);
13 | }
14 |
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/laplacian.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function laplacian () {
6 | return convolution([
7 | -1, -1, -1,
8 | -1, 8, -1,
9 | -1, -1, -1
10 | ]);
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/motion-blur-2.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function motionBlur2 () {
6 | return convolution([
7 | 1, 0, 0, 0, 0, 0, 0, 0, 1,
8 | 0, 1, 0, 0, 0, 0, 0, 1, 0,
9 | 0, 0, 1, 0, 0, 0, 1, 0, 0,
10 | 0, 0, 0, 1, 0, 1, 0, 0, 0,
11 | 0, 0, 0, 0, 1, 0, 0, 0, 0,
12 | 0, 0, 0, 1, 0, 1, 0, 0, 0,
13 | 0, 0, 1, 0, 0, 0, 1, 0, 0,
14 | 0, 1, 0, 0, 0, 0, 0, 1, 0,
15 | 1, 0, 0, 0, 0, 0, 0, 0, 1,
16 | ]);
17 | }
18 |
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/motion-blur-3.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function motionBlur3 () {
6 | return convolution([
7 | 1, 0, 0, 0, 1, 0, 0, 0, 1,
8 | 0, 1, 0, 0, 1, 0, 0, 1, 0,
9 | 0, 0, 1, 0, 1, 0, 1, 0, 0,
10 | 0, 0, 0, 1, 1, 1, 0, 0, 0,
11 | 1, 1, 1, 1, 1, 1, 1, 1, 1,
12 | 0, 0, 0, 1, 1, 1, 0, 0, 0,
13 | 0, 0, 1, 0, 1, 0, 1, 0, 0,
14 | 0, 1, 0, 0, 1, 0, 0, 1, 0,
15 | 1, 0, 0, 0, 1, 0, 0, 0, 1,
16 | ]);
17 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/motion-blur.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function motionBlur () {
6 | return convolution([
7 | 1, 0, 0, 0, 0, 0, 0, 0, 0,
8 | 0, 1, 0, 0, 0, 0, 0, 0, 0,
9 | 0, 0, 1, 0, 0, 0, 0, 0, 0,
10 | 0, 0, 0, 1, 0, 0, 0, 0, 0,
11 | 0, 0, 0, 0, 1, 0, 0, 0, 0,
12 | 0, 0, 0, 0, 0, 1, 0, 0, 0,
13 | 0, 0, 0, 0, 0, 0, 1, 0, 0,
14 | 0, 0, 0, 0, 0, 0, 0, 1, 0,
15 | 0, 0, 0, 0, 0, 0, 0, 0, 1,
16 | ]);
17 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/negative.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function negative () {
6 | return convolution([
7 | -1, 0, 0, 0, 0,
8 | 0, -1, 0, 0, 0,
9 | 0, 0, -1, 0, 0,
10 | 0, 0, 0, 1, 0,
11 | 1, 1, 1, 1, 1
12 | ]);
13 | }
14 |
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/normal.js:
--------------------------------------------------------------------------------
1 | import { convolution } from '../util'
2 | export default function () {
3 | return convolution([
4 | 0, 0, 0,
5 | 0, 1, 0,
6 | 0, 0, 0
7 | ])
8 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/sepia2.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function sepia2 () {
6 | return convolution([
7 | 0.393, 0.349, 0.272, 0, 0,
8 | 0.769, 0.686, 0.534, 0, 0,
9 | 0.189, 0.168, 0.131, 0, 0,
10 | 0, 0, 0, 0, 0,
11 | 0, 0, 0, 0, 0
12 | ]);
13 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/sharpen.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function sharpen () {
6 | return convolution([
7 | 0, -1, 0,
8 | -1, 5, -1,
9 | 0, -1, 0
10 | ]);
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/sobel-horizontal.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function sobelHorizontal () {
6 | return convolution([
7 | -1, -2, -1,
8 | 0, 0, 0,
9 | 1, 2, 1
10 | ]);
11 | }
12 |
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/sobel-vertical.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function sobelVertical () {
6 | return convolution([
7 | -1, 0, 1,
8 | -2, 0, 2,
9 | -1, 0, 1
10 | ]);
11 | }
12 |
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/transparency.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution
3 | } from '../util'
4 |
5 | export default function transparency () {
6 | return convolution([
7 | 1, 0, 0, 0, 0,
8 | 0, 1, 0, 0, 0,
9 | 0, 0, 1, 0, 0,
10 | 0, 0, 0, 0.3, 0,
11 | 0, 0, 0, 0, 1,
12 | ]);
13 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/matrix/unsharp-masking.js:
--------------------------------------------------------------------------------
1 | import {
2 | convolution,
3 | weight
4 | } from '../util'
5 |
6 | export default function unsharpMasking () {
7 | return convolution(weight([
8 | 1, 4, 6, 4, 1,
9 | 4, 16, 24, 16, 4,
10 | 6, 24, -476, 24, 6,
11 | 4, 16, 24, 16, 4,
12 | 1, 4, 6, 4, 1
13 | ], -1 / 256));
14 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/multi/index.js:
--------------------------------------------------------------------------------
1 | import kirsch from './kirsch'
2 | import sobel from './sobel'
3 | import vintage from './vintage'
4 |
5 | export default {
6 | kirsch,
7 | sobel,
8 | vintage
9 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/multi/kirsch.js:
--------------------------------------------------------------------------------
1 | import {
2 | multi
3 | } from '../util'
4 |
5 | export default function kirsch () {
6 | return multi('kirsch-horizontal kirsch-vertical');
7 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/multi/sobel.js:
--------------------------------------------------------------------------------
1 | import {
2 | multi
3 | } from '../util'
4 |
5 | export default function sobel () {
6 | return multi('sobel-horizontal sobel-vertical');
7 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/multi/vintage.js:
--------------------------------------------------------------------------------
1 | import {
2 | multi
3 | } from '../util'
4 |
5 | export default function vintage () {
6 | return multi(`brightness(0.15) saturation(-0.2) gamma(1.8)`)
7 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/bitonal.js:
--------------------------------------------------------------------------------
1 | import Color from '../../../Color'
2 | import {
3 | shader,
4 | colorToVec4,
5 | toFloatString
6 | } from '../util'
7 |
8 | export default function bitonal(darkColor, lightColor, threshold = 0.5) {
9 | let checkVlue = toFloatString(threshold)
10 | let darkColorString = colorToVec4(Color.parse(darkColor))
11 | let lightColorString = colorToVec4(Color.parse(lightColor))
12 |
13 | return shader(`
14 | if ((pixelColor.r + pixelColor.g + pixelColor.b) > ${checkVlue}) {
15 | outColor = vec4(${lightColorString}.rgb, pixelColor.a);
16 | } else {
17 | outColor = vec4(${darkColorString}.rgb, pixelColor.a);
18 | }
19 | `);
20 | }
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/brightness.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader, toFloatString, parseParamNumber
3 | } from '../util'
4 |
5 | /*
6 | * @param {Number} amount -1..1 , value < 0 is darken, value > 0 is brighten
7 | */
8 | export default function brightness (amount = 1) {
9 | const C = toFloatString( parseParamNumber(amount) );
10 |
11 | return shader(`
12 | outColor = pixelColor + (${C});
13 | `);
14 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/brownie.js:
--------------------------------------------------------------------------------
1 | import matrix from './matrix'
2 |
3 | export default function brownie () {
4 |
5 | return matrix(
6 | 0.5997023498159715,0.34553243048391263,-0.2708298674538042,0,
7 | -0.037703249837783157,0.8609577587992641,0.15059552388459913,0,
8 | 0.24113635128153335,-0.07441037908422492,0.44972182064877153,0,
9 | 0,0,0,1
10 | )
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/chaos.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | export default function chaos (amount = 10) {
8 | const C = toFloatString( parseParamNumber(amount) );
9 |
10 | return shader(`
11 | vec2 st = pixelColor.st;
12 | st *= ${C};
13 |
14 | vec2 ipos = floor(st); // get the integer coords
15 |
16 | vec3 color = vec3(random( ipos ));
17 |
18 | outColor = vec4(color, pixelColor.a);
19 | `);
20 | }
21 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/clip.js:
--------------------------------------------------------------------------------
1 |
2 | import {
3 | shader, toFloatString, parseParamNumber
4 | } from '../util'
5 |
6 | /*
7 | * @param {Number} amount 0..1
8 | */
9 | export default function clip (amount = 0) {
10 | const C = toFloatString(parseParamNumber(amount))
11 |
12 | return shader(`
13 | outColor = vec4(
14 | (pixelColor.r > 1.0 - ${C}) ? 1.0 : 0.0,
15 | (pixelColor.g > 1.0 - ${C}) ? 1.0 : 0.0,
16 | (pixelColor.b > 1.0 - ${C}) ? 1.0 : 0.0,
17 | pixelColor.a
18 | );
19 | `);
20 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/contrast.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | /*
8 | * @param {Number} amount 0..1
9 | */
10 | export default function contrast (amount = 1) {
11 | const C = toFloatString(parseParamNumber(amount));
12 |
13 | return shader(`
14 | outColor = pixelColor * ${C};
15 | `);
16 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/gamma.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | /*
8 | * @param {Number} amount -1..1 , value < 0 is darken, value > 0 is brighten
9 | */
10 | export default function gamma (amount = 1) {
11 | const C = toFloatString( parseParamNumber(amount) )
12 |
13 | return shader(`
14 | outColor = vec4(pow(pixelColor.r, ${C}), pow(pixelColor.g, ${C}), pow(pixelColor.b, ${C}), pixelColor.a );
15 | `);
16 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/gradient.js:
--------------------------------------------------------------------------------
1 | import Color from '../../../Color'
2 | import {
3 | shader,
4 | colorToVec4,
5 | toFloatString
6 | } from '../util'
7 | /**
8 | * F.gradient('red', 'blue', 'yellow', 'white', 10)
9 | * F.gradient('red, blue, yellow, white, 10')
10 | */
11 | export default function gradient () {
12 | // 전체 매개변수 기준으로 파싱
13 | // 색이 아닌 것 기준으로 scale 변수로 인식
14 |
15 | let params = [...arguments];
16 |
17 | if (params.length === 1 && typeof params[0] === 'string') {
18 | params = Color.convertMatchesArray(params[0])
19 | }
20 |
21 | params = params.map(arg => {
22 | return arg
23 | }).join(', ')
24 |
25 | let colors = Color.parseGradient(params);
26 |
27 | colors[0][1] = 0;
28 | colors[colors.length-1][1] = 1;
29 |
30 | colors = colors.map(c => {
31 | const {r, g, b, a} = Color.parse(c[0])
32 | return [{r, g, b, a}, c[1]];
33 | })
34 |
35 | let temp = []
36 |
37 | for(var i = 0, len = colors.length; i < len - 1; i++) {
38 | const start = colors[i];
39 | const end = colors[i+1];
40 |
41 | const startColor = colorToVec4(start[0])
42 | const endColor = colorToVec4(end[0])
43 |
44 | const startRate = toFloatString (start[1]);
45 | const endRate = toFloatString (end[1]);
46 |
47 | temp.push(`
48 | if (${startRate} <= rate && rate < ${endRate}) {
49 | outColor = mix(${startColor}, ${endColor}, (rate - ${startRate})/(${endRate} - ${startRate}));
50 | }
51 | `)
52 | }
53 |
54 | return shader(`
55 | float rate = (pixelColor.r * 0.2126 + pixelColor.g * 0.7152 + pixelColor.b * 0.0722);
56 |
57 | ${temp.join('\n')}
58 | `)
59 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/grayscale.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber
3 | } from '../util'
4 |
5 | import matrix from './matrix'
6 |
7 | /**
8 | *
9 | * @param {Number} amount 0..1
10 | */
11 | export default function grayscale (amount = 1) {
12 | let C = parseParamNumber(amount);
13 |
14 | if (C > 1) C = 1;
15 |
16 | return matrix(
17 | (0.2126 + 0.7874 * (1 - C)), (0.7152 - 0.7152 * (1 - C)), (0.0722 - 0.0722 * (1 - C)), 0,
18 | (0.2126 - 0.2126 * (1 - C)), (0.7152 + 0.2848 * (1 - C)), (0.0722 - 0.0722 * (1 - C)), 0,
19 | (0.2126 - 0.2126 * (1 - C)), (0.7152 - 0.7152 * (1 - C)), (0.0722 + 0.9278 * (1 - C)), 0,
20 | 0, 0, 0, 1
21 | );
22 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/hue.js:
--------------------------------------------------------------------------------
1 | //http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
2 | import {
3 | shader,
4 | parseParamNumber,
5 | toFloatString
6 | } from '../util'
7 |
8 | /*
9 | * @param {Number} amount 0..1 , (real value 0..360)
10 | */
11 | export default function hue (amount = 1) {
12 | const C = toFloatString( parseParamNumber(amount))
13 |
14 | return shader(`
15 | vec3 hsv = rgb2hsv(pixelColor.rgb);
16 | hsv.x += ${C};
17 | outColor = vec4(hsv2rgb(hsv).rgb, pixelColor.a);
18 | `);
19 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/index.js:
--------------------------------------------------------------------------------
1 |
2 | import bitonal from './bitonal'
3 | import brightness from './brightness'
4 | import brownie from './brownie'
5 | import clip from './clip'
6 | import chaos from './chaos'
7 | import contrast from './contrast'
8 | import gamma from './gamma'
9 | import gradient from './gradient'
10 | import grayscale from './grayscale'
11 | import hue from './hue'
12 | import invert from './invert'
13 | import kodachrome from './kodachrome'
14 | import matrix from './matrix'
15 | import noise from './noise'
16 | import opacity from './opacity'
17 | import polaroid from './polaroid'
18 | import saturation from './saturation'
19 | import sepia from './sepia'
20 | import shade from './shade'
21 | import shift from './shift'
22 | import solarize from './solarize'
23 | import technicolor from './technicolor'
24 | import threshold from './threshold'
25 | import thresholdColor from './threshold-color'
26 | import tint from './tint'
27 |
28 | export default {
29 | bitonal,
30 | brightness,
31 | brownie,
32 | clip,
33 | chaos,
34 | contrast,
35 | gamma,
36 | gradient,
37 | grayscale,
38 | hue,
39 | invert,
40 | kodachrome,
41 | matrix,
42 | noise,
43 | opacity,
44 | polaroid,
45 | saturation,
46 | sepia,
47 | shade,
48 | shift,
49 | solarize,
50 | technicolor,
51 | threshold,
52 | 'threshold-color': thresholdColor,
53 | tint
54 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/invert.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | export default function invert (amount = 1) {
8 | const C = toFloatString( parseParamNumber(amount) );
9 |
10 | return shader(`
11 | outColor = vec4(
12 | (1.0 - pixelColor.r) * ${C},
13 | (1.0 - pixelColor.g) * ${C},
14 | (1.0 - pixelColor.b) * ${C},
15 | pixelColor.a
16 | );
17 | `);
18 | }
19 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/kodachrome.js:
--------------------------------------------------------------------------------
1 | import matrix from './matrix'
2 |
3 | export default function kodachrome () {
4 |
5 | return matrix(
6 | 1.1285582396593525,-0.3967382283601348,-0.03992559172921793,0,
7 | -0.16404339962244616,1.0835251566291304,-0.05498805115633132,0,
8 | -0.16786010706155763,-0.5603416277695248,1.6014850761964943,0,
9 | 0,0,0,1
10 | )
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/matrix.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | toFloatString
4 | } from '../util'
5 |
6 | export default function matrix (
7 | $a = 0, $b = 0, $c = 0, $d = 0,
8 | $e = 0, $f = 0, $g = 0, $h = 0,
9 | $i = 0, $j = 0, $k = 0, $l = 0,
10 | $m = 0, $n = 0, $o = 0, $p = 0
11 | ) {
12 |
13 | const matrix = [
14 | $a, $b, $c, $d,
15 | $e, $f, $g, $h,
16 | $i, $j, $k, $l,
17 | $m, $n, $o, $p
18 | ].map(toFloatString)
19 |
20 | return shader(`
21 |
22 | outColor = vec4(
23 | ${matrix[0]} * pixelColor.r + ${matrix[1]} * pixelColor.g + ${matrix[2]} * pixelColor.b + ${matrix[3]} * pixelColor.a,
24 | ${matrix[4]} * pixelColor.r + ${matrix[5]} * pixelColor.g + ${matrix[6]} * pixelColor.b + ${matrix[7]} * pixelColor.a,
25 | ${matrix[8]} * pixelColor.r + ${matrix[9]} * pixelColor.g + ${matrix[10]} * pixelColor.b + ${matrix[11]} * pixelColor.a,
26 | ${matrix[12]} * pixelColor.r + ${matrix[13]} * pixelColor.g + ${matrix[14]} * pixelColor.b + ${matrix[15]} * pixelColor.a
27 | );
28 | `);
29 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/noise.js:
--------------------------------------------------------------------------------
1 | import { shader, parseParamNumber, toFloatString } from '../util';
2 |
3 |
4 | /**
5 | *
6 | * @param {Number} amount 0..1
7 | */
8 | export default function noise (amount = 1) {
9 |
10 | const C = Math.abs( parseParamNumber(amount))
11 | const min = toFloatString( -C )
12 | const max = toFloatString( C )
13 | return shader(`
14 | float rnd = ${min} + random( pixelColor.st ) * (${max} - ${min});
15 |
16 | outColor = vec4(pixelColor.rgb + rnd, 1.0);
17 | `);
18 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/opacity.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | /**
8 | *
9 | * @param {Number} amount 0..1
10 | */
11 | export default function opacity (amount = 1) {
12 | const C = toFloatString( parseParamNumber(amount));
13 |
14 | return shader(`
15 | outColor = vec4(pixelColor.rgb, pixelColor.a * ${C});
16 | `);
17 | }
18 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/polaroid.js:
--------------------------------------------------------------------------------
1 | import matrix from './matrix'
2 |
3 | export default function polaroid () {
4 |
5 | return matrix(
6 | 1.438,-0.062,-0.062,0,
7 | -0.122,1.378,-0.122,0,
8 | -0.016,-0.016,1.483,0,
9 | 0,0,0,1
10 | )
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/saturation.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber
3 | } from '../util'
4 | import matrix from './matrix'
5 |
6 |
7 | /*
8 | * @param {Number} amount 0..1
9 | */
10 | export default function saturation (amount = 0) {
11 | const L = 1 - Math.abs(parseParamNumber(amount));
12 |
13 | return matrix(
14 | L, 0, 0, 0,
15 | 0, L, 0, 0,
16 | 0, 0, L, 0,
17 | 0, 0, 0, L
18 | )
19 |
20 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/sepia.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber
3 | } from '../util';
4 | import matrix from "./matrix";
5 |
6 | /*
7 | * @param {Number} amount 0..100
8 | */
9 | export default function sepia (amount = 1) {
10 | let C = parseParamNumber(amount);
11 | if (C > 1) C = 1;
12 |
13 | return matrix(
14 | (0.393 + 0.607 * (1 - C)), (0.769 - 0.769 * (1 - C)), (0.189 - 0.189 * (1 - C)), 0,
15 | (0.349 - 0.349 * (1 - C)), (0.686 + 0.314 * (1 - C)), (0.168 - 0.168 * (1 - C)), 0,
16 | (0.272 - 0.272 * (1 - C)), (0.534 - 0.534 * (1 - C)), (0.131 + 0.869 * (1 - C)), 0,
17 | 0, 0, 0, 1
18 | )
19 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/shade.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | export default function shade(redValue = 1, greenValue = 1, blueValue = 1) {
8 | const r = toFloatString(parseParamNumber(redValue) / 255)
9 | const g = toFloatString(parseParamNumber(greenValue) /255)
10 | const b = toFloatString(parseParamNumber(blueValue) /255)
11 |
12 | return shader(`
13 | outColor = vec4(
14 | pixelColor.r * ${r},
15 | pixelColor.g * ${g},
16 | pixelColor.b * ${b},
17 | pixelColor.a
18 | );
19 | `);
20 | }
21 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/shift.js:
--------------------------------------------------------------------------------
1 | import matrix from './matrix'
2 |
3 | export default function shift () {
4 |
5 | return matrix(
6 | 1.438,-0.062,-0.062,0,
7 | -0.122,1.378,-0.122,0,
8 | -0.016,-0.016,1.483,0,
9 | 0,0,0,1
10 | );
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/solarize.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber,
4 | toFloatString
5 | } from '../util'
6 |
7 | export default function solarize (redValue, greenValue, blueValue) {
8 | const r = toFloatString( parseParamNumber(redValue) )
9 | const g = toFloatString( parseParamNumber(greenValue) )
10 | const b = toFloatString( parseParamNumber(blueValue) )
11 |
12 | return shader(`
13 | outColor = vec4(
14 | (pixelColor.r < ${r}) ? 1.0 - pixelColor.r: pixelColor.r,
15 | (pixelColor.g < ${g}) ? 1.0 - pixelColor.g: pixelColor.g,
16 | (pixelColor.b < ${b}) ? 1.0 - pixelColor.b: pixelColor.b,
17 | pixelColor.a
18 | );
19 | `);
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/technicolor.js:
--------------------------------------------------------------------------------
1 | import matrix from './matrix'
2 |
3 | export default function technicolor () {
4 |
5 | return matrix(
6 | 1.9125277891456083,-0.8545344976951645,-0.09155508482755585,0,
7 | -0.3087833385928097,1.7658908555458428,-0.10601743074722245,0,
8 | -0.231103377548616,-0.7501899197440212,1.847597816108189,0,
9 | 0,0,0,1
10 | )
11 | }
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/threshold-color.js:
--------------------------------------------------------------------------------
1 | import {
2 | parseParamNumber,
3 | shader,
4 | toFloatString
5 | } from '../util'
6 |
7 | export default function thresholdColor (scale = 1) {
8 | scale = toFloatString( parseParamNumber(scale) )
9 |
10 | return shader(`
11 | float c = ( (pixelColor.r * 0.2126 + pixelColor.g * 0.7152 + pixelColor.b * 0.0722) ) >= ${scale} ? 1.0 : 0.0;
12 |
13 | outColor = vec4(c, c, c, pixelColor.a);
14 | `)
15 | }
16 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/threshold.js:
--------------------------------------------------------------------------------
1 | import thresholdColor from './threshold-color'
2 | /*
3 | * @param {Number} amount 0..100
4 | */
5 | export default function threshold (scale = 200, amount = 100) {
6 | return thresholdColor(scale, amount, false)
7 | }
8 |
--------------------------------------------------------------------------------
/src/util/gl/filter/pixel/tint.js:
--------------------------------------------------------------------------------
1 | import {
2 | shader,
3 | parseParamNumber
4 | } from '../util'
5 |
6 | /**
7 | *
8 | * @param {*} redTint 0..1
9 | * @param {*} greenTint 0..1
10 | * @param {*} blueTint 0..1
11 | */
12 | export default function (redTint = 0, greenTint = 0, blueTint = 0) {
13 | const r = parseParamNumber(redTint)
14 | const g = parseParamNumber(greenTint)
15 | const b = parseParamNumber(blueTint)
16 |
17 | return shader(`
18 | outColor = vec4(
19 | pixelColor.r += (1 - pixelColor.r) * ${r},
20 | pixelColor.g += (1 - pixelColor.g) * ${g},
21 | pixelColor.b += (1 - pixelColor.b) * ${b},
22 | pixelColor.a
23 | );
24 | `);
25 | }
26 |
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | import Color from './Color'
2 | import HueColor from './HueColor'
3 | import ColorNames from './ColorNames'
4 | import ImageFilter from './ImageFilter'
5 | import GL from './GL'
6 | import Canvas from './Canvas'
7 | import ImageLoader from './ImageLoader'
8 |
9 | export default {
10 | Color,
11 | HueColor,
12 | ColorNames,
13 | ImageFilter,
14 | GL,
15 | Canvas,
16 | ImageLoader
17 | }
--------------------------------------------------------------------------------
/test/util.Blend.spec.js:
--------------------------------------------------------------------------------
1 | import Blender from '../src/util/Blender'
2 | import Color from '../src/util/Color'
3 |
4 | test('Blend - normal', () => {
5 | const back = Color.parse('#255050');
6 | const source = Color.parse('#2550ff');
7 |
8 | var rgb = Blender.normal(back, source);
9 |
10 | expect(rgb).toEqual({ r : 0x25, g : 0x50, b: 0xff, a : 1 });
11 |
12 | rgb = Blender.multiply(back, source);
13 |
14 | console.log(rgb);
15 | });
16 |
--------------------------------------------------------------------------------
/test/util.Filter.spec.js:
--------------------------------------------------------------------------------
1 | import Filter from '../src/util/Filter'
2 | import Color from '../src/util/Color'
3 |
4 | test('gray filter', () => {
5 | const colorCode = Color.parse('#255050');
6 |
7 | let testData = [colorCode.r, colorCode.g, colorCode.b];
8 |
9 | Filter.grayscale(testData);
10 |
11 | expect(testData).toEqual([ 71, 71, 71 ]);
12 | });
13 |
--------------------------------------------------------------------------------
/test/util.ImageFilter.spec.js:
--------------------------------------------------------------------------------
1 | import ImageFilter from '../src/util/ImageFilter'
2 | import Color from '../src/util/Color'
3 |
4 | test('image gray filter', () => {
5 | const colorCode = Color.parse('#255050');
6 |
7 | const buffer = [
8 | colorCode.r, colorCode.g, colorCode.b, 255
9 | ]
10 |
11 | const filter = ImageFilter.grayscale();
12 |
13 | var rgb = filter(buffer);
14 |
15 | expect(rgb).toEqual([ 71, 71, 71, 255]);
16 | });
17 |
--------------------------------------------------------------------------------