├── .gitignore ├── Gruntfile.js ├── README.md ├── build ├── almond.js ├── qtek.image.js └── wrap │ ├── end.js │ └── start.js ├── dist ├── emage.js └── emage.min.js ├── example ├── file_upload │ ├── 1.jpg │ ├── 10.jpg │ ├── 11.jpg │ ├── 12.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ ├── 9.jpg │ ├── list.json │ └── thumb │ │ ├── 1.jpg │ │ ├── 10.jpg │ │ ├── 11.jpg │ │ ├── 12.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ ├── 7.jpg │ │ ├── 8.jpg │ │ └── 9.jpg ├── static-dist │ ├── app.js │ ├── build.txt │ ├── controllerConfig.js │ ├── index.html │ ├── lib.js │ ├── lut │ │ ├── amatorka.png │ │ ├── bleachbypass.png │ │ ├── candlelight.png │ │ ├── crispwarm.png │ │ ├── crispwinter.png │ │ ├── dropblues.png │ │ ├── edgyamber.png │ │ ├── fallcolors.png │ │ ├── filmstock_50.png │ │ ├── foggynight.png │ │ ├── futuristicbleak.png │ │ ├── horrorblue.png │ │ ├── latesunset.png │ │ ├── lookup.png │ │ ├── missetikate.png │ │ ├── moonlight.png │ │ ├── nightfromday.png │ │ ├── soft_elegance_1.png │ │ ├── soft_elegance_2.png │ │ ├── softwarming.png │ │ ├── tealorangepluscontrast.png │ │ └── tensiongreen.png │ ├── modules │ │ ├── app.xml │ │ ├── common │ │ │ ├── histogram.js │ │ │ ├── iconbutton.js │ │ │ ├── list.js │ │ │ ├── listitem.js │ │ │ ├── modal.js │ │ │ ├── nativehtml.js │ │ │ └── region.js │ │ ├── filters │ │ │ ├── filter.html │ │ │ ├── filter.js │ │ │ ├── filters.xml │ │ │ ├── index.js │ │ │ └── source.js │ │ ├── imagelist │ │ │ ├── imageitem.js │ │ │ ├── imagelist.xml │ │ │ └── index.js │ │ ├── module.js │ │ ├── navigator │ │ │ ├── imageitem.js │ │ │ ├── index.js │ │ │ ├── navigator.xml │ │ │ └── navlink.js │ │ ├── router.js │ │ └── viewport │ │ │ ├── index.js │ │ │ ├── viewport.js │ │ │ └── viewport.xml │ ├── preview │ │ ├── amatorka.jpg │ │ ├── bleachbypass.jpg │ │ ├── candlelight.jpg │ │ ├── canny.jpg │ │ ├── crispwarm.jpg │ │ ├── crispwinter.jpg │ │ ├── dropblues.jpg │ │ ├── edgyamber.jpg │ │ ├── fallcolors.jpg │ │ ├── filmstock_50.jpg │ │ ├── foggynight.jpg │ │ ├── futuristicbleak.jpg │ │ ├── gaussian.jpg │ │ ├── grayscale.jpg │ │ ├── horrorblue.jpg │ │ ├── latesunset.jpg │ │ ├── missetikate.jpg │ │ ├── moonlight.jpg │ │ ├── nightfromday.jpg │ │ ├── original.jpg │ │ ├── sepia.jpg │ │ ├── sketch.jpg │ │ ├── smoothtoon.jpg │ │ ├── sobel.jpg │ │ ├── softelegance.jpg │ │ ├── softwarming.jpg │ │ ├── tealorangepluscontrast.jpg │ │ ├── tensiongreen.jpg │ │ ├── threshold.jpg │ │ └── toon.jpg │ ├── style │ │ ├── animate.css │ │ ├── app.css │ │ ├── app.less │ │ ├── imgs │ │ │ ├── add.svg │ │ │ ├── arrow-left-active.svg │ │ │ ├── arrow-left-hover.svg │ │ │ ├── arrow-left.svg │ │ │ ├── arrow-right-active.svg │ │ │ ├── arrow-right-hover.svg │ │ │ ├── arrow-right.svg │ │ │ ├── black-Linen.png │ │ │ ├── camera.svg │ │ │ ├── cloud.svg │ │ │ ├── local.svg │ │ │ └── picture.svg │ │ └── qpf │ │ │ ├── base.css │ │ │ ├── base.less │ │ │ ├── css-vendor.less │ │ │ └── images │ │ │ ├── arrow-down.svg │ │ │ ├── arrow-up.svg │ │ │ ├── check_radio_sheet.png │ │ │ ├── link-active.png │ │ │ ├── link.png │ │ │ └── slider-control.png │ └── text.js └── static │ ├── app.js │ ├── boot.js │ ├── controllerConfig.js │ ├── index-dist.html │ ├── index.html │ ├── lib │ ├── LAB.js │ ├── async.js │ ├── director.js │ ├── emage.js │ ├── jquery.js │ ├── knockout.js │ ├── ko.mapping.js │ ├── less.js │ ├── qpf.js │ ├── require.js │ └── underscore.js │ ├── lut │ ├── amatorka.png │ ├── bleachbypass.png │ ├── candlelight.png │ ├── crispwarm.png │ ├── crispwinter.png │ ├── dropblues.png │ ├── edgyamber.png │ ├── fallcolors.png │ ├── filmstock_50.png │ ├── foggynight.png │ ├── futuristicbleak.png │ ├── horrorblue.png │ ├── latesunset.png │ ├── lookup.png │ ├── missetikate.png │ ├── moonlight.png │ ├── nightfromday.png │ ├── soft_elegance_1.png │ ├── soft_elegance_2.png │ ├── softwarming.png │ ├── tealorangepluscontrast.png │ └── tensiongreen.png │ ├── modules │ ├── app.xml │ ├── common │ │ ├── histogram.js │ │ ├── iconbutton.js │ │ ├── list.js │ │ ├── listitem.js │ │ ├── modal.js │ │ ├── nativehtml.js │ │ └── region.js │ ├── filters │ │ ├── filter.html │ │ ├── filter.js │ │ ├── filters.xml │ │ ├── index.js │ │ └── source.js │ ├── imagelist │ │ ├── imageitem.js │ │ ├── imagelist.xml │ │ └── index.js │ ├── module.js │ ├── navigator │ │ ├── imageitem.js │ │ ├── index.js │ │ ├── navigator.xml │ │ └── navlink.js │ ├── router.js │ └── viewport │ │ ├── index.js │ │ ├── viewport.js │ │ └── viewport.xml │ ├── preview │ ├── amatorka.jpg │ ├── bleachbypass.jpg │ ├── candlelight.jpg │ ├── canny.jpg │ ├── crispwarm.jpg │ ├── crispwinter.jpg │ ├── dropblues.jpg │ ├── edgyamber.jpg │ ├── fallcolors.jpg │ ├── filmstock_50.jpg │ ├── foggynight.jpg │ ├── futuristicbleak.jpg │ ├── gaussian.jpg │ ├── grayscale.jpg │ ├── horrorblue.jpg │ ├── latesunset.jpg │ ├── missetikate.jpg │ ├── moonlight.jpg │ ├── nightfromday.jpg │ ├── original.jpg │ ├── sepia.jpg │ ├── sketch.jpg │ ├── smoothtoon.jpg │ ├── sobel.jpg │ ├── softelegance.jpg │ ├── softwarming.jpg │ ├── tealorangepluscontrast.jpg │ ├── tensiongreen.jpg │ ├── threshold.jpg │ └── toon.jpg │ ├── style │ ├── animate.css │ ├── app.less │ ├── imgs │ │ ├── add.svg │ │ ├── arrow-left-active.svg │ │ ├── arrow-left-hover.svg │ │ ├── arrow-left.svg │ │ ├── arrow-right-active.svg │ │ ├── arrow-right-hover.svg │ │ ├── arrow-right.svg │ │ ├── black-Linen.png │ │ ├── camera.svg │ │ ├── cloud.svg │ │ ├── local.svg │ │ └── picture.svg │ └── qpf │ │ ├── base.less │ │ ├── css-vendor.less │ │ └── images │ │ ├── arrow-down.svg │ │ ├── arrow-up.svg │ │ ├── check_radio_sheet.png │ │ ├── link-active.png │ │ ├── link.png │ │ └── slider-control.png │ └── text.js ├── package.json ├── src ├── buildin │ ├── blur.js │ ├── boxblur.js │ ├── coloradjust.js │ ├── colormatrix.js │ ├── gaussian.js │ ├── grayscale.js │ ├── hue.js │ ├── lensblur.js │ ├── lut.js │ ├── sepia.js │ ├── shaders │ │ ├── _imagedirectionalnonmaximumsuppression.essl │ │ ├── _nonmaxiumsuppression.essl │ │ ├── _weakpixelinclusion.essl │ │ ├── alphablend.essl │ │ ├── box_blur.essl │ │ ├── colormatrix.essl │ │ ├── convolution.essl │ │ ├── gamma.essl │ │ ├── hexagonal_blur.essl │ │ ├── histogram.essl │ │ ├── hue.essl │ │ ├── level.essl │ │ ├── lut.essl │ │ ├── sketch.essl │ │ ├── sobel.essl │ │ ├── thresholdedge.essl │ │ └── toon.essl │ ├── sketch.js │ ├── sobel.js │ └── toon.js ├── emage.js ├── fx.js ├── histogram.js ├── layer.js ├── processor.js └── text.js ├── tests ├── histogram.html ├── test.html └── test.js ├── thirdparty ├── qtek.image.js └── require.js └── update.sh /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt){ 2 | 3 | function removeTextPlugin(moduleName, path, content){ 4 | // Remove the text plugin and convert to a normal module 5 | // Or the text plugin will have some problem when optimize the project based on emage which also has a text plugin 6 | // https://groups.google.com/forum/?fromgroups#!msg/requirejs/jiaDogbA1EQ/jKrHL0gs21UJ 7 | // http://stackoverflow.com/questions/10196977/how-can-i-prevent-the-require-js-optimizer-from-including-the-text-plugin-in-opt 8 | content = content.replace(/define\([\'\"]text\!(.*?)[\'\"]/g, "define('$1'"); 9 | // in dependencies 10 | content = content.replace(/define\((.*?)\[(.*?)\]/g, function(str, moduleId, dependencies){ 11 | dependencies = dependencies.split(","); 12 | for(var i = 0; i < dependencies.length; i++){ 13 | if(dependencies[i]){ 14 | dependencies[i] = dependencies[i].replace(/[\'\"]text\!(.*?)[\'\"]/, "'$1'"); 15 | } 16 | } 17 | return "define(" + moduleId + "[" + dependencies.join(",") + "]"; 18 | }) 19 | content = content.replace(/require\([\'\"]text\!(.*?)[\'\"]\)/g, "require('$1')"); 20 | return content; 21 | } 22 | 23 | grunt.initConfig({ 24 | concat : { 25 | script : { 26 | } 27 | }, 28 | uglify : { 29 | build : { 30 | files : { 31 | "dist/emage.min.js" : ['dist/emage.js'] 32 | } 33 | } 34 | }, 35 | copy : { 36 | build : { 37 | files : [{ 38 | src : "dist/emage.js", 39 | dest : "example/static/lib/emage.js" 40 | }] 41 | }, 42 | example : { 43 | files : [{ 44 | src : "example/static-dist/index-dist.html", 45 | dest : "example/static-dist/index.html" 46 | }] 47 | } 48 | }, 49 | less : { 50 | example : { 51 | files : { 52 | "example/static-dist/style/app.css" : "example/static-dist/style/app.less", 53 | "example/static-dist/style/qpf/base.css" : "example/static-dist/style/qpf/base.less" 54 | } 55 | } 56 | }, 57 | concat : { 58 | example : { 59 | src : ["example/static/lib/require.js", "example/static/lib/director.js"], 60 | dest : "example/static-dist/lib.js" 61 | } 62 | }, 63 | clean : { 64 | example : ["example/static-dist/lib", 65 | "example/static-dist/boot.js", 66 | "example/static-dist/index-dist.html"] 67 | }, 68 | requirejs : { 69 | build : { 70 | options : { 71 | baseUrl : "./", 72 | paths : { 73 | "text" : "src/text", 74 | "shaders" : "src/buildin/shaders", 75 | "qtek" : "thirdparty/qtek.image" 76 | }, 77 | name : "build/almond", 78 | include : ["src/emage"], 79 | exclude : ['text'], 80 | optimize : "none", 81 | wrap : { 82 | 'startFile' : 'build/wrap/start.js', 83 | 'endFile' : 'build/wrap/end.js' 84 | }, 85 | out : "dist/emage.js", 86 | onBuildWrite : removeTextPlugin 87 | } 88 | }, 89 | example : { 90 | options : { 91 | appDir : 'example/static', 92 | baseUrl : "./", 93 | dir : 'example/static-dist', 94 | paths : { 95 | async : "lib/async", 96 | qpf : "lib/qpf", 97 | emage : "lib/emage", 98 | knockout : "lib/knockout", 99 | "$" : "lib/jquery", 100 | "_" : "lib/underscore" 101 | }, 102 | shim : { 103 | '$' : { 104 | exports : "$" 105 | }, 106 | '_' : { 107 | exports : "_" 108 | }, 109 | "app" : ["modules/filters/index", 110 | "modules/navigator/index", 111 | "modules/viewport/index"] 112 | }, 113 | // optimize : "none", 114 | waitSeconds : 30, 115 | modules : [{ 116 | name : "app" 117 | }] 118 | } 119 | } 120 | } 121 | }) 122 | 123 | grunt.loadNpmTasks('grunt-contrib-uglify'); 124 | grunt.loadNpmTasks('grunt-contrib-concat'); 125 | grunt.loadNpmTasks('grunt-contrib-clean'); 126 | grunt.loadNpmTasks('grunt-contrib-copy'); 127 | grunt.loadNpmTasks('grunt-contrib-requirejs'); 128 | grunt.loadNpmTasks('grunt-contrib-less'); 129 | 130 | grunt.registerTask("default", ["requirejs:build", "uglify:build", "copy:build"]); 131 | grunt.registerTask("example", ["requirejs:build", 132 | "uglify:build", 133 | "copy:build", 134 | "requirejs:example", 135 | "concat:example", 136 | "copy:example", 137 | "less:example", 138 | "clean:example"]); 139 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EMAGE 2 | ========== 3 | 4 | EMAGE is a webgl based image processing library, it is based on the webgl library [qtek](https://github.com/pissang/qtek). 5 | 6 | The [example](http://pissang.github.com/emage/example/#/) 7 | 8 | #### Simple Usage 9 | 10 | Import the library 11 | 12 | 13 | 14 | Or in the AMD environment 15 | ```js 16 | var emage = require("emage") 17 | ``` 18 | Process the image 19 | ```js 20 | // Create a image processor 21 | var processor = new emage.Processor(canvas, image); 22 | 23 | // Create a layer 24 | var blurLayer = new emage.Layer(); 25 | 26 | // Use gaussian blur 27 | blurLayer.use("buildin.gaussian"); 28 | 29 | // Create an other layer for color adjustment 30 | var colorLayer = new emage.Layer("buildin.coloradjust"); 31 | 32 | // Add layers to processor and update the image 33 | processor.add(blurLayer); 34 | processor.add(colorLayer); 35 | processor.update(); 36 | 37 | // Replace the gaussian blur with lens blur and update again 38 | blurLayer.use("buildin.lensblur"); 39 | processor.update(); 40 | 41 | // Set parameters of filter 42 | blurLayer.set("brightness", 6.0); 43 | blurLayer.set("blurSize", 4.0); 44 | 45 | // Or you can also write like this 46 | blurLayer.set({ 47 | brightness : 6.0, 48 | blurSize : 4.0 49 | }) 50 | 51 | // Export the final image 52 | var canvas = emage.canvas; 53 | var img = new Image; 54 | img.src = canvas.toDataURL(); 55 | ``` 56 | 57 | #### Supported filters 58 | 59 | Most of the filters is from [GPUImage](https://github.com/BradLarson/GPUImage) 60 | 61 | ----- 62 | ##### Gaussian Blur 63 | 64 | buildin.gaussian 65 | 66 | + blurSize : 2.0 67 | 68 | ----- 69 | ##### Box Blur 70 | 71 | buildin.boxblur 72 | 73 | + blurSize : 2.0 74 | 75 | ----- 76 | ##### Lens Blur 77 | 78 | buildin.lensblur 79 | 80 | + blurSize : 0.4 81 | + brightness : 6.0 82 | 83 | ----- 84 | ##### Color Adjust 85 | 86 | buildin.coloradjust 87 | 88 | + brightness : 0.0 89 | + gamma : 1.0 90 | + contrast : 1.0 91 | + exposure : 0.0 92 | + saturation : 1.0 93 | 94 | ----- 95 | ##### Color Matrix 96 | 97 | buildin.colormatrix 98 | 99 | + colorMatrix : [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] 100 | + intensity : 1.0 101 | 102 | ----- 103 | ##### Sepia 104 | 105 | buildin.sepia 106 | 107 | ----- 108 | ##### Color Lookup 109 | 110 | buildin.lut 111 | 112 | + lookup : Image 113 | 114 | ----- 115 | ##### Sobel Edge Detection 116 | 117 | buildin.sobel 118 | 119 | ----- 120 | ##### Toon Effect 121 | 122 | buildin.toon 123 | 124 | ----- 125 | ##### Sketch Effect 126 | 127 | buildin.sketch 128 | 129 | 130 | #### Histogram compute 131 | 132 | Histogram compute is done in shaders and can be quite efficient 133 | ```js 134 | // Pass in the image you want to compute histogram 135 | var histogram = new emage.Histogram(image); 136 | 137 | // Set down sample rate 138 | histogram.downSample = 1/4; 139 | 140 | // Compute the histogram and get the result 141 | histogram.update(); 142 | // It will return a UnitArray(256) which store the histogram of red channel 143 | var redChannel = histogram.channels.red; 144 | // And other channels 145 | var blueChannel = histogram.channels.blue; 146 | var luminanceChannel = histogram.channels.luminance; 147 | ``` 148 | -------------------------------------------------------------------------------- /build/qtek.image.js: -------------------------------------------------------------------------------- 1 | define( function(require){ 2 | 3 | var exportsObject = { 4 | "2d": { 5 | "Gradient": require('2d/gradient'), 6 | "Layer": require('2d/layer'), 7 | "LinearGradient": require('2d/lineargradient'), 8 | "Node": require('2d/node'), 9 | "Pattern": require('2d/pattern'), 10 | "picking": { 11 | "Box": require('2d/picking/box'), 12 | "Pixel": require('2d/picking/pixel') 13 | }, 14 | // "RadialGradient": require('2d/radialgradient'), 15 | "shape": { 16 | // "Arc": require('2d/shape/arc'), 17 | // "Circle": require('2d/shape/circle'), 18 | // "Ellipse": require('2d/shape/ellipse'), 19 | // "HTML": require('2d/shape/html'), 20 | // "Image": require('2d/shape/image'), 21 | // "Line": require('2d/shape/line'), 22 | "Path": require('2d/shape/path'), 23 | // "Polygon": require('2d/shape/polygon'), 24 | // "Rectangle": require('2d/shape/rectangle'), 25 | // "RoundedRectangle": require('2d/shape/roundedrectangle'), 26 | // "Sector": require('2d/shape/sector'), 27 | // "SVGPath": require('2d/shape/svgpath'), 28 | // "Text": require('2d/shape/text'), 29 | // "TextBox": require('2d/shape/textbox') 30 | }, 31 | "Stage": require('2d/stage'), 32 | "Style": require('2d/style'), 33 | "util": require('2d/util') 34 | }, 35 | "3d": { 36 | "Bone": require('3d/bone'), 37 | "BoundingBox": require('3d/boundingbox'), 38 | "Camera": require('3d/camera'), 39 | "camera": { 40 | // "Orthographic": require('3d/camera/orthographic'), 41 | "Perspective": require('3d/camera/perspective') 42 | }, 43 | "Compositor": require('3d/compositor'), 44 | "compositor": { 45 | "Graph": require('3d/compositor/graph'), 46 | "Group": require('3d/compositor/group'), 47 | "Node": require('3d/compositor/node'), 48 | "Pass": require('3d/compositor/pass'), 49 | "SceneNode": require('3d/compositor/scenenode'), 50 | "TextureNode": require('3d/compositor/texturenode'), 51 | "TexturePool": require('3d/compositor/texturepool') 52 | }, 53 | // "debug": { 54 | // "Pointlight": require('3d/debug/pointlight'), 55 | // "RenderInfo": require('3d/debug/renderinfo') 56 | // }, 57 | "FrameBuffer": require('3d/framebuffer'), 58 | "Geometry": require('3d/geometry'), 59 | "geometry": { 60 | // "Cube": require('3d/geometry/cube'), 61 | "Plane": require('3d/geometry/plane'), 62 | // "Sphere": require('3d/geometry/sphere') 63 | }, 64 | "Light": require('3d/light'), 65 | // "light": { 66 | // "Ambient": require('3d/light/ambient'), 67 | // "Directional": require('3d/light/directional'), 68 | // "Point": require('3d/light/point'), 69 | // "Spot": require('3d/light/spot') 70 | // }, 71 | "Material": require('3d/material'), 72 | "Mesh": require('3d/mesh'), 73 | "Node": require('3d/node'), 74 | // "plugin": { 75 | // "FirstPersonControl": require('3d/plugin/firstpersoncontrol'), 76 | // "OrbitControl": require('3d/plugin/orbitcontrol'), 77 | // "Skybox": require('3d/plugin/skybox'), 78 | // "Skydome": require('3d/plugin/skydome') 79 | // }, 80 | // "prepass": { 81 | // "Reflection": require('3d/prepass/reflection'), 82 | // "ShadowMap": require('3d/prepass/shadowmap') 83 | // }, 84 | "Renderer": require('3d/renderer'), 85 | "Scene": require('3d/scene'), 86 | "Shader": require('3d/shader'), 87 | "shader": { 88 | // "library": require('3d/shader/library') 89 | }, 90 | // "Skeleton": require('3d/skeleton'), 91 | "Texture": require('3d/texture'), 92 | "texture": { 93 | "Texture2D": require('3d/texture/texture2d'), 94 | // "TextureCube": require('3d/texture/texturecube') 95 | }, 96 | "util": { 97 | "mesh": require('3d/util/mesh') 98 | }, 99 | "WebGLInfo": require('3d/webglinfo') 100 | }, 101 | "animation": { 102 | "Animation": require('animation/animation'), 103 | "Clip": require('animation/clip'), 104 | "Easing": require('animation/easing') 105 | }, 106 | "core": { 107 | "Base": require('core/base'), 108 | "Cache": require('core/cache'), 109 | "Event": require('core/event'), 110 | "Matrix2": require('core/matrix2'), 111 | "Matrix2d": require('core/matrix2d'), 112 | "Matrix3": require('core/matrix3'), 113 | "Matrix4": require('core/matrix4'), 114 | "mixin": { 115 | "derive": require('core/mixin/derive'), 116 | "notifier": require('core/mixin/notifier') 117 | }, 118 | "Quaternion": require('core/quaternion'), 119 | "requester": require('core/request'), 120 | "Vector2": require('core/vector2'), 121 | "Vector3": require('core/vector3'), 122 | "Vector4": require('core/vector4') 123 | }, 124 | "Engine": require('engine'), 125 | // "loader": { 126 | // "GLTF": require('loader/gltf'), 127 | // "InstantGeometry": require('loader/instantgeometry'), 128 | // "SVG": require('loader/svg'), 129 | // "three": { 130 | // "Model": require('loader/three/model') 131 | // } 132 | // }, 133 | "util": { 134 | "Color": require('util/color'), 135 | "Util": require('util/util') 136 | } 137 | }; 138 | 139 | var glMatrix = require('glmatrix'); 140 | exportsObject.math = glMatrix; 141 | 142 | return exportsObject; 143 | }) -------------------------------------------------------------------------------- /build/wrap/end.js: -------------------------------------------------------------------------------- 1 | 2 | var emage = require("src/emage"); 3 | for(var name in emage){ 4 | _exports[name] = emage[name]; 5 | } 6 | }) -------------------------------------------------------------------------------- /build/wrap/start.js: -------------------------------------------------------------------------------- 1 | (function(factory){ 2 | // AMD 3 | if( typeof define !== "undefined" && define["amd"] ){ 4 | define( ["exports"], factory.bind(window) ); 5 | // No module loader 6 | }else{ 7 | factory(window["emage"] = {}); 8 | } 9 | 10 | })(function(_exports){ 11 | -------------------------------------------------------------------------------- /example/file_upload/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/1.jpg -------------------------------------------------------------------------------- /example/file_upload/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/10.jpg -------------------------------------------------------------------------------- /example/file_upload/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/11.jpg -------------------------------------------------------------------------------- /example/file_upload/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/12.jpg -------------------------------------------------------------------------------- /example/file_upload/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/2.jpg -------------------------------------------------------------------------------- /example/file_upload/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/3.jpg -------------------------------------------------------------------------------- /example/file_upload/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/4.jpg -------------------------------------------------------------------------------- /example/file_upload/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/5.jpg -------------------------------------------------------------------------------- /example/file_upload/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/6.jpg -------------------------------------------------------------------------------- /example/file_upload/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/7.jpg -------------------------------------------------------------------------------- /example/file_upload/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/8.jpg -------------------------------------------------------------------------------- /example/file_upload/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/9.jpg -------------------------------------------------------------------------------- /example/file_upload/list.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "url" : "../file_upload/1.jpg", 3 | "thumb" : "../file_upload/thumb/1.jpg" 4 | }, { 5 | "url" : "../file_upload/2.jpg", 6 | "thumb" : "../file_upload/thumb/2.jpg" 7 | }, { 8 | "url" : "../file_upload/3.jpg", 9 | "thumb" : "../file_upload/thumb/3.jpg" 10 | }, { 11 | "url" : "../file_upload/4.jpg", 12 | "thumb" : "../file_upload/thumb/4.jpg" 13 | }, { 14 | "url" : "../file_upload/5.jpg", 15 | "thumb" : "../file_upload/thumb/5.jpg" 16 | }, { 17 | "url" : "../file_upload/6.jpg", 18 | "thumb" : "../file_upload/thumb/6.jpg" 19 | }, { 20 | "url" : "../file_upload/7.jpg", 21 | "thumb" : "../file_upload/thumb/7.jpg" 22 | }, { 23 | "url" : "../file_upload/8.jpg", 24 | "thumb" : "../file_upload/thumb/8.jpg" 25 | }, { 26 | "url" : "../file_upload/9.jpg", 27 | "thumb" : "../file_upload/thumb/9.jpg" 28 | }, { 29 | "url" : "../file_upload/10.jpg", 30 | "thumb" : "../file_upload/thumb/10.jpg" 31 | }, { 32 | "url" : "../file_upload/11.jpg", 33 | "thumb" : "../file_upload/thumb/11.jpg" 34 | }, { 35 | "url" : "../file_upload/12.jpg", 36 | "thumb" : "../file_upload/thumb/12.jpg" 37 | }] -------------------------------------------------------------------------------- /example/file_upload/thumb/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/1.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/10.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/11.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/12.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/2.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/3.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/4.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/5.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/6.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/7.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/8.jpg -------------------------------------------------------------------------------- /example/file_upload/thumb/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/file_upload/thumb/9.jpg -------------------------------------------------------------------------------- /example/static-dist/build.txt: -------------------------------------------------------------------------------- 1 | 2 | style/animate.css 3 | ---------------- 4 | style/animate.css 5 | 6 | app.js 7 | ---------------- 8 | lib/qpf.js 9 | lib/underscore.js 10 | lib/knockout.js 11 | lib/jquery.js 12 | modules/module.js 13 | text.js 14 | text!modules/filters/filters.xml 15 | text!modules/filters/filter.html 16 | text!modules/viewport/viewport.xml 17 | modules/viewport/viewport.js 18 | lib/emage.js 19 | modules/viewport/index.js 20 | modules/filters/filter.js 21 | modules/filters/source.js 22 | modules/filters/index.js 23 | text!modules/navigator/navigator.xml 24 | modules/navigator/navlink.js 25 | modules/router.js 26 | modules/navigator/index.js 27 | text!modules/app.xml 28 | controllerConfig.js 29 | modules/common/histogram.js 30 | modules/common/listitem.js 31 | modules/common/list.js 32 | modules/common/modal.js 33 | modules/common/region.js 34 | modules/common/iconbutton.js 35 | modules/common/nativehtml.js 36 | app.js 37 | -------------------------------------------------------------------------------- /example/static-dist/controllerConfig.js: -------------------------------------------------------------------------------- 1 | define({navigator:{"modules/navigator/index":{url:"*"}},viewport:{"modules/viewport/index":{url:"*"}},filters:{"modules/filters/index":{url:"*"}},imageList:{"modules/imagelist/index":{url:"*"}}}); -------------------------------------------------------------------------------- /example/static-dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EMAGE 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /example/static-dist/lut/amatorka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/amatorka.png -------------------------------------------------------------------------------- /example/static-dist/lut/bleachbypass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/bleachbypass.png -------------------------------------------------------------------------------- /example/static-dist/lut/candlelight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/candlelight.png -------------------------------------------------------------------------------- /example/static-dist/lut/crispwarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/crispwarm.png -------------------------------------------------------------------------------- /example/static-dist/lut/crispwinter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/crispwinter.png -------------------------------------------------------------------------------- /example/static-dist/lut/dropblues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/dropblues.png -------------------------------------------------------------------------------- /example/static-dist/lut/edgyamber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/edgyamber.png -------------------------------------------------------------------------------- /example/static-dist/lut/fallcolors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/fallcolors.png -------------------------------------------------------------------------------- /example/static-dist/lut/filmstock_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/filmstock_50.png -------------------------------------------------------------------------------- /example/static-dist/lut/foggynight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/foggynight.png -------------------------------------------------------------------------------- /example/static-dist/lut/futuristicbleak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/futuristicbleak.png -------------------------------------------------------------------------------- /example/static-dist/lut/horrorblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/horrorblue.png -------------------------------------------------------------------------------- /example/static-dist/lut/latesunset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/latesunset.png -------------------------------------------------------------------------------- /example/static-dist/lut/lookup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/lookup.png -------------------------------------------------------------------------------- /example/static-dist/lut/missetikate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/missetikate.png -------------------------------------------------------------------------------- /example/static-dist/lut/moonlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/moonlight.png -------------------------------------------------------------------------------- /example/static-dist/lut/nightfromday.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/nightfromday.png -------------------------------------------------------------------------------- /example/static-dist/lut/soft_elegance_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/soft_elegance_1.png -------------------------------------------------------------------------------- /example/static-dist/lut/soft_elegance_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/soft_elegance_2.png -------------------------------------------------------------------------------- /example/static-dist/lut/softwarming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/softwarming.png -------------------------------------------------------------------------------- /example/static-dist/lut/tealorangepluscontrast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/tealorangepluscontrast.png -------------------------------------------------------------------------------- /example/static-dist/lut/tensiongreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/lut/tensiongreen.png -------------------------------------------------------------------------------- /example/static-dist/modules/app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/static-dist/modules/common/histogram.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","emage","knockout"],function(e){var t=e("qpf"),n=e("emage"),r=e("knockout"),i=n.qtek["2d"],s=n.qtek.core.Vector2,o=t.use("meta/meta"),u=o.derive(function(){return{image:null,_layer:new i.Layer({enablePicking:!1}),_paths:{red:new i.shape.Path({stroke:!1,style:new i.Style({fill:"red",globalAlpha:.4,shadow:"0 -2 2 #333"})}),green:new i.shape.Path({stroke:!1,style:new i.Style({fill:"green",globalAlpha:.4,shadow:"0 -2 2 #333"})}),blue:new i.shape.Path({stroke:!1,style:new i.Style({fill:"blue",globalAlpha:.4,shadow:"0 -2 2 #333"})}),redStroke:new i.shape.Path({fill:!1,style:new i.Style({stroke:"#950000",globalAlpha:.7})}),greenStroke:new i.shape.Path({fill:!1,style:new i.Style({stroke:"#009500",globalAlpha:.7})}),blueStroke:new i.shape.Path({fill:!1,style:new i.Style({stroke:"#000095",globalAlpha:.7})})},size:128,sample:r.observable(2),_histogram:new n.Histogram}},{type:"HISTOGRAM",css:"histogram",initialize:function(){this._layer.add(this._paths.red),this._layer.add(this._paths.green),this._layer.add(this._paths.blue),this._layer.add(this._paths.redStroke),this._layer.add(this._paths.greenStroke),this._layer.add(this._paths.blueStroke),this._histogram.downSample=1/8},template:"",update:function(){if(!this.image)return;this._histogram.image=this.image,this._histogram.update()},refresh:function(){if(!this.image)return;histogramArray=this.getNormalizedHistogram(),this.updatePath("red",histogramArray.red),this.updatePath("green",histogramArray.green),this.updatePath("blue",histogramArray.blue),this._layer.render()},initPath:function(e){var t=this._paths[e],n=this.height(),r=this.sample(),i=this.$el.width()/256*r;t.segments=[{point:new s(0,n)}];var o=0;for(var u=0;u<256;u+=r)t.segments.push({point:new s(o,0)}),o+=i;t.pushPoints([new s(this.$el.width(),n),new s(0,n)]),this._paths[e+"Stroke"].segments=t.segments},updatePath:function(e,t){var n=this._paths[e],r=this.height(),i=this.sample();for(var s=i;s<257;s+=i)n.segments[s/i].point.y=(1-t[s-1])*r},getNormalizedHistogram:function(){function e(e){var t=[];for(var n=0;n"),icon:i.observable("")}},{type:"ICONBUTTON",css:_.union("icon-button",n.prototype.css),template:'
'});return r.provideBinding("iconbutton",s),s}); -------------------------------------------------------------------------------- /example/static-dist/modules/common/list.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","./listitem","knockout"],function(e){var t=e("qpf"),n=e("./listitem"),r=t.use("container/container"),i=e("knockout"),s=r.derive(function(){return{dataSource:i.observableArray([]),itemView:i.observable(n),selected:i.observable()}},{type:"LIST",css:"list",template:'
',initialize:function(){var e=_.clone(this.dataSource()),t=this;this.dataSource.subscribe(function(t){this._update(e,t),e=_.clone(t),_.each(e,function(e,t){i.utils.unwrapObservable(e.selected)&&this.selected(t)},this)},this),this.selected.subscribe(function(e){this._unSelectAll();var t=this.children()[e];t&&t.$el.addClass("selected")},this),this.$el.delegate(".qpf-container-item","click",function(){var e=i.contextFor(this);t.selected(e.$index())}),this._update([],e)},_update:function(e,t){var n=this.children(),r=this.itemView(),s=[],o=i.utils.compareArrays(e,t),u=[];_.each(o,function(t){if(t.status==="retained"){var i=e.indexOf(t.value);s[i]=n[i]}else if(t.status==="added"){var o=new r({attributes:t.value});s[t.index]=o,n.splice(t.index,0,o),u.push(o)}},this),this.children(s),_.each(u,function(e){e.render()})},_unSelectAll:function(){_.each(this.children(),function(e,t){e.$el.removeClass("selected")},this)}});return r.provideBinding("list",s),s}); -------------------------------------------------------------------------------- /example/static-dist/modules/common/listitem.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout"],function(e){var t=e("qpf"),n=t.use("meta/meta"),r=e("knockout"),i=n.derive(function(){return{title:r.observable(""),icon:r.observable(""),href:r.observable("")}},{type:"LISTITEM",css:"list-item",initialize:function(){this.$el.mousedown(function(e){e.preventDefault()});var e=this;this.$el.click(function(){var t=e.href();t&&t.indexOf("#")==0&&(window.location.hash=t)})},template:'
'});return i}); -------------------------------------------------------------------------------- /example/static-dist/modules/common/modal.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout"],function(e){var t=e("qpf"),n=t.use("core/clazz"),r=t.use("container/window"),i=t.use("container/container"),s=t.use("container/inline"),o=t.use("meta/button"),u=e("knockout"),a=new r({attributes:{"class":"qpf-modal"}}),f=new i,l=new s,c=new o({attributes:{text:"确 定"}}),h=new o({attributes:{text:"取 消"}});a.add(f),a.add(l),l.add(c),l.add(h),a.render(),document.body.appendChild(a.$el[0]);var p=$('
');document.body.appendChild(p[0]),a.$el.hide(),p.hide();var d=n.derive(function(){return{title:"",body:null,onApply:function(e){e()},onCancel:function(e){e()}}},{show:function(){var e=this;a.title(this.title),f.removeAll(),this.body&&f.add(this.body),c.off("click"),h.off("click"),c.on("click",function(){e.onApply(e.hide)}),h.on("click",function(){e.onCancel(e.hide)}),a.$el.show(),p.show(),a.left(($(window).width()-a.$el.width())/2),a.top(($(window).height()-a.$el.height())/2-100)},hide:function(){a.$el.hide(),p.hide()}});return d.popup=function(e,t,n,r){var i=new d({title:e,body:t,onApply:n||function(e){e()},onCancel:r||function(e){e()}});i.body.render(),i.show()},d.confirm=function(e,t,n,r){var i=new d({title:e,body:new Label({attributes:{text:t},temporary:!0}),onApply:n||function(e){e()},onCancel:r||function(e){e()}});i.body.render(),i.show()},d}); -------------------------------------------------------------------------------- /example/static-dist/modules/common/nativehtml.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout","_"],function(e){var t=e("qpf"),n=t.use("meta/meta"),r=e("knockout"),i=t.use("core/xmlparser"),s=e("_"),o=n.derive(function(){return{$el:$('
'),html:r.observable("ko")}},{type:"NATIVEHTML",css:"native-html"});return n.provideBinding("nativehtml",o),i.provideParser("nativehtml",function(e){var t=i.util.getChildren(e),n="";s.each(t,function(e){e.nodeType===4&&(n+=e.textContent)});if(n)return{html:n}}),o}); -------------------------------------------------------------------------------- /example/static-dist/modules/common/region.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout","_","../router"],function(e){var t=e("qpf"),n=t.use("meta/meta"),r=t.use("base"),i=e("knockout"),s=e("_"),o=e("../router"),u=r.derive(function(){return{controller:{},_moduleCache:{},_currentModule:null}},{type:"REGION",css:"region",initialize:function(){var e=this;s.each(this.controller,function(t,n){var r=t.url,i=t.context;r==="*"?e.enterModule(n,{},function(){}):(o.on("after",r,e.leaveModule.bind(e,n)),o.on(r,e.enterModule.bind(e,n,i)))})},_updateStatus:function(){var e=this,t=Array.prototype.pop.call(arguments),n=0;s.each(e._moduleCache,function(e){n++,e.__enable__?e.enable(t):e.disable(t)}),n||t()},leaveModule:function(e){var t=this._moduleCache[e],n=Array.prototype.pop.call(arguments);t&&t.disable(n)},enterModule:function(t,n){var r={},i=this,o=Array.prototype.pop.call(arguments),u=Array.prototype.slice.call(arguments,2);n&&s.each(u,function(e,t){var i=n[t];i&&(r[i]=e)});var a=this._moduleCache[t];a?(a.enable(o),a.setContext(r),this._currentModule=a,this.onResize()):e([t],function(e){if(e&&e.start){var n=e.start();n&&i.$el.append(n),e.mainComponent.parent=i,e.enable(o),e.setContext(r),i._moduleCache[t]=e,i._currentModule=e,i.onResize()}}),o()},onResize:function(){this._currentModule&&this._currentModule.mainComponent&&(this._currentModule.mainComponent.width(this.$el.width()),this._currentModule.mainComponent.height(this.$el.height())),r.prototype.onResize.call(this)}});return n.provideBinding("region",u),u}); -------------------------------------------------------------------------------- /example/static-dist/modules/filters/filter.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |
8 |
-------------------------------------------------------------------------------- /example/static-dist/modules/filters/filter.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout","text!./filter.html","../viewport/index"],function(e){var t=e("qpf"),n=t.use("widget/widget"),r=e("knockout"),i=e("text!./filter.html"),s=e("../viewport/index"),o=n.derive(function(){var e={title:r.observable(""),preview:r.observable(""),description:r.observable(""),name:r.observable(""),parameters:r.observable({}),use:function(){s.filterLayer.use(this.name());var e=this.parameters(),t=!1;if(e){s.filterLayer.set(e);var n=0;for(var r in e)if(e[r]instanceof Image){var i=e[r];i.complete||(t=!0,n++,i.onload=function(){n--,n==0&&s.update()})}}t||s.update()}};return e._previewSrc=r.computed(function(){if(e.preview())return e.preview()}),e},{type:"FILTER",css:"filter",template:i});return o}); -------------------------------------------------------------------------------- /example/static-dist/modules/filters/filters.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/static-dist/modules/filters/index.js: -------------------------------------------------------------------------------- 1 | define(["require","../module","text!./filters.xml","qpf","./filter","./source","../viewport/index","_","knockout"],function(e){var t=e("../module"),n=e("text!./filters.xml"),r=e("qpf"),i=e("./filter"),s=e("./source"),o=e("../viewport/index"),u=e("_"),a=e("knockout"),f=new t({name:"filters",xml:n,filters:a.observableArray(s.filters),FilterView:i,seachKeyword:a.observable(""),colorAdjust:{brightness:a.observable(0),contrast:a.observable(1),exposure:a.observable(0),gamma:a.observable(1),saturation:a.observable(1)},hue:a.observable(0)}),l;return f.on("start",function(){l=f.mainComponent.$el.find("#Histogram").qpf("get")[0],l.image=o.processor.canvas,l.update(),l.refresh()}),a.computed(function(){o.colorAdjustLayer.set({brightness:f.colorAdjust.brightness(),contrast:f.colorAdjust.contrast(),exposure:f.colorAdjust.exposure(),gamma:f.colorAdjust.gamma(),saturation:f.colorAdjust.saturation()}),o.hueLayer.set("hue",f.hue()),o.update()}),o.on("update",function(){l.update(),l.refresh()}),f.seachKeyword.subscribe(function(e){e?f.filters(u.filter(f.filters(),function(t){return t.name.indexOf(e.toLowerCase())>=0||t.title.indexOf(e)>=0})):f.filters(s.filters)}),f}); -------------------------------------------------------------------------------- /example/static-dist/modules/filters/source.js: -------------------------------------------------------------------------------- 1 | define([],function(){function e(e){var t=new Image;return t.src=e,t}var t={filters:[{title:"Gaussian",name:"buildin.gaussian",preview:"preview/gaussian.jpg",description:""},{title:"lensblur",name:"buildin.lensblur",preview:"preview/gaussian.jpg",description:""},{title:"Sepia",name:"buildin.sepia",preview:"preview/sepia.jpg",description:""},{title:"Miss Etikate",name:"buildin.lut",parameters:{lookup:e("lut/missetikate.png")},preview:"preview/missetikate.jpg",description:""},{title:"Amatorka",name:"buildin.lut",parameters:{lookup:e("lut/amatorka.png")},preview:"preview/amatorka.jpg",description:""},{title:"Bleach Bypass",name:"buildin.lut",parameters:{lookup:e("lut/bleachbypass.png")},preview:"preview/bleachbypass.jpg",description:""},{title:"Candle Light",name:"buildin.lut",parameters:{lookup:e("lut/candlelight.png")},preview:"preview/candlelight.jpg",description:""},{title:"Crisp Warm",name:"buildin.lut",parameters:{lookup:e("lut/crispwarm.png")},preview:"preview/crispwarm.jpg",description:""},{title:"Crisp Winter",name:"buildin.lut",parameters:{lookup:e("lut/crispwinter.png")},preview:"preview/crispwinter.jpg",description:""},{title:"Drop Blues",name:"buildin.lut",parameters:{lookup:e("lut/dropblues.png")},preview:"preview/dropblues.jpg",description:""},{title:"Edgy Amber",name:"buildin.lut",parameters:{lookup:e("lut/edgyamber.png")},preview:"preview/edgyamber.jpg",description:""},{title:"Fall Colors",name:"buildin.lut",parameters:{lookup:e("lut/fallcolors.png")},preview:"preview/fallcolors.jpg",description:""},{title:"Film Stock 50",name:"buildin.lut",parameters:{lookup:e("lut/filmstock_50.png")},preview:"preview/filmstock_50.jpg",description:""},{title:"Foggy Night",name:"buildin.lut",parameters:{lookup:e("lut/foggynight.png")},preview:"preview/foggynight.jpg",description:""},{title:"Futuristic Bleak",name:"buildin.lut",parameters:{lookup:e("lut/futuristicbleak.png")},preview:"preview/futuristicbleak.jpg",description:""},{title:"Horror Blue",name:"buildin.lut",parameters:{lookup:e("lut/horrorblue.png")},preview:"preview/horrorblue.jpg",description:""},{title:"Late Sunset",name:"buildin.lut",parameters:{lookup:e("lut/latesunset.png")},preview:"preview/latesunset.jpg",description:""},{title:"Moonlight",name:"buildin.lut",parameters:{lookup:e("lut/moonlight.png")},preview:"preview/moonlight.jpg",description:""},{title:"Night From Day",name:"buildin.lut",parameters:{lookup:e("lut/nightfromday.png")},preview:"preview/nightfromday.jpg",description:""},{title:"Soft Warming",name:"buildin.lut",parameters:{lookup:e("lut/softwarming.png")},preview:"preview/softwarming.jpg",description:""},{title:"Teal Orange Plus...",name:"buildin.lut",parameters:{lookup:e("lut/tealorangepluscontrast.png")},preview:"preview/tealorangepluscontrast.jpg",description:""},{title:"Tension Green",name:"buildin.lut",parameters:{lookup:e("lut/tensiongreen.png")},preview:"preview/tensiongreen.jpg",description:""},{title:"Grayscale",name:"buildin.grayscale",preview:"preview/grayscale.jpg"},{title:"Sketch",name:"buildin.sketch",preview:"preview/sketch.jpg"},{title:"Toon",name:"buildin.toon",preview:"preview/toon.jpg"}]};return t}); -------------------------------------------------------------------------------- /example/static-dist/modules/imagelist/imageitem.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout"],function(e){var t=e("qpf"),n=t.use("meta/meta"),r=e("knockout"),i=n.derive(function(){return{title:r.observable(""),thumb:r.observable(""),url:r.observable()}},{type:"IMAGEITEM",css:"image-item",initialize:function(){this.$el.mousedown(function(e){e.preventDefault()})},template:'
'});return r.bindingHandlers.qpf_image={init:function(e,t){e.innerHTML="";var n=r.utils.unwrapObservable(t());if(typeof n=="string"){var i=document.createElement("img");i.src=n}else var i=n;e.appendChild(i)}},i}); -------------------------------------------------------------------------------- /example/static-dist/modules/imagelist/imagelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/static-dist/modules/imagelist/index.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout","../module","text!./imagelist.xml","../common/list","./imageitem","../viewport/index"],function(e){function d(){l=Math.max(0,l-1),a.images(f.slice(l*c,Math.min(f.length,(l+1)*c)))}function v(){l=Math.min(l+1,h),a.images(f.slice(l*c,Math.min(f.length,(l+1)*c)))}var t=e("qpf"),n=e("knockout"),r=e("../module"),i=e("text!./imagelist.xml"),s=e("../common/list"),o=e("./imageitem"),u=e("../viewport/index"),a=new r({name:"imagelist",xml:i,images:n.observableArray(),ImageItem:o}),f,l=0,c=5,h;$.get("../file_upload/list.json",function(e){f=e,h=Math.floor(f.length/c-1e-5),a.images(f.slice(0,c))});var p;return a.$el.delegate(".qpf-ui-image-item","click",function(){var e=$(this).find("img")[0];u.setImage(e),p=new Image,p.onload=function(){u.setImage(p)},p.src=$(this).qpf("get")[0].url()}).delegate(".button-left","click",d).delegate(".button-right","click",v),a}); -------------------------------------------------------------------------------- /example/static-dist/modules/module.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout"],function(e){var t=e("qpf"),n=t.use("base"),r=e("knockout"),i=t.use("core/xmlparser"),s=t.use("core/mixin/derive"),o=t.use("core/mixin/event"),u=new Function;_.extend(u,s),_.extend(u.prototype,o);var a=u.derive(function(){return{name:"",$el:$("
"),xml:"",context:{},mainComponent:null}},{start:function(){return this.xml&&this.applyXML(this.xml),this.trigger("start"),this.$el},enable:function(e){this.$el.show(),this.trigger("enable"),e&&e()},disable:function(e){this.$el.hide(),this.trigger("disable"),e&&e()},setContext:function(e){this._defaultContext||(this._defaultContext={},_.each(this.context,function(e,t){this._defaultContext[t]=e()},this));for(var t in this.context)typeof e[t]!="undefined"?this.context[t](e[t]):this.context[t](this._defaultContext[t]);n.prototype._mappingAttributes.call(this.context,e,!0)},dispose:function(){n.disposeByDom(this.$el[0]),this.$el.remove()},loadingStart:function(){this._$mask&&this._$mask.addClass("loading").show()},loadingEnd:function(){this._$mask&&this._$mask.removeClass("loading").hide()},applyXML:function(e){i.parse(e,this.$el[0]),r.applyBindings(this,this.$el[0]);var t=this.$el[0].firstChild;t&&(this.mainComponent=n.getByDom(t))}});return a}); -------------------------------------------------------------------------------- /example/static-dist/modules/navigator/imageitem.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout"],function(e){var t=e("qpf"),n=t.use("meta/meta"),r=e("knockout"),i=n.derive(function(){return{title:r.observable(""),image:r.observable("")}},{type:"IMAGEITEM",css:"image-item",initialize:function(){this.$el.mousedown(function(e){e.preventDefault()})},template:'
'});return r.bindingHandlers.qpf_image={init:function(e,t){e.innerHTML="";var n=r.utils.unwrapObservable(t());if(typeof n=="string"){var i=document.createElement("img");i.src=n}else var i=n;e.appendChild(i)}},i}); -------------------------------------------------------------------------------- /example/static-dist/modules/navigator/index.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout","../module","text!./navigator.xml","./navlink","../viewport/index","../router"],function(e){function l(){function t(){console.log(arguments)}o.on("beforerender",function(){tex.needsUpdate=!0});var e={video:!0};navigator.getUserMedia?navigator.getUserMedia(e,function(e){f.src=e,f.play()},t):navigator.webkitGetUserMedia&&navigator.webkitGetUserMedia(e,function(e){f.src=window.webkitURL.createObjectURL(e),f.play()},t)}var t=e("qpf"),n=e("knockout"),r=e("../module"),i=e("text!./navigator.xml"),s=e("./navlink"),o=e("../viewport/index"),u=e("../router"),a=new r({name:"navigator",xml:i});a.$el.delegate(".qpf-ui-navlink","click",function(){var e=$(this),t=e.qpf("get")[0];if(t)switch(t.icon()){case"camera":break;case"cloud":}a.$el.find(".qpf-ui-navlink").removeClass("active"),e.addClass("active")});var f;return a}); -------------------------------------------------------------------------------- /example/static-dist/modules/navigator/navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/static-dist/modules/navigator/navlink.js: -------------------------------------------------------------------------------- 1 | define(["qpf","knockout"],function(){var e=require("qpf"),t=e.use("meta/meta"),n=require("knockout"),r=t.derive(function(){return{icon:n.observable(),title:n.observable(""),href:n.observable("")}},{type:"NAVLINK",css:"navlink",initialize:function(){var e=this;this.$el.click(function(t){window.location.hash="#/"+e.href()})},template:'
'});return t.provideBinding("navlink",r),r}); -------------------------------------------------------------------------------- /example/static-dist/modules/router.js: -------------------------------------------------------------------------------- 1 | define(["require"],function(e){var t=Router();return t.configure({recurse:"forward"}),t}); -------------------------------------------------------------------------------- /example/static-dist/modules/viewport/index.js: -------------------------------------------------------------------------------- 1 | define(["require","../module","text!./viewport.xml","./viewport","qpf","knockout","$","emage","_"],function(e){function c(e){e.stopPropagation(),e.preventDefault();var t=e.dataTransfer.files[0];t&&t.type.match(/image/)&&h(t)}function h(e){l.onload=function(e){var t=new Image;l.onload=null,t.onload=function(){t.onload=null,f.setImage(t),f.mainComponent.$el.find(".draghint").remove()},t.src=e.target.result},l.readAsDataURL(e)}var t=e("../module"),n=e("text!./viewport.xml"),r=e("./viewport"),i=e("qpf"),s=e("knockout"),o=e("$"),u=e("emage"),a=e("_"),f=new t({name:"viewport",xml:n,applyFilter:s.observable(!0),resize:function(){if(f.mainComponent&&f.mainComponent.parent&&this.processor.image){var e=this.processor.image,t=e.height/e.width,n=f.mainComponent,r=n.parent.width(),i=n.parent.height();t<1?(n.$el.css({"margin-top":(i-r*t)/2+"px","margin-left":"0px"}),n.height(r*t),n.width(r)):(n.$el.css({"margin-left":(r-i/t)/2,"margin-top":"0px"}),n.width(i/t),n.height(i))}},onResize:function(){f.resize()},setImage:function(e){this.processor.image=e,this.update(),this.resize()},update:a.throttle(function(){f.processor.image&&(f.processor.update(),this.trigger("update"))},100),processor:new u.Processor,loadImageFromFile:h,colorAdjustLayer:null,hueLayer:null,filterLayer:null});f.on("start",function(){f.mainComponent.$el.find("canvas").replaceWith(this.processor.canvas);var e=new u.Layer;f.processor.add(e);var t=new u.Layer("buildin.coloradjust"),n=new u.Layer("buildin.hue");f.processor.add(t),f.processor.add(n),this.colorAdjustLayer=t,this.filterLayer=e,this.hueLayer=n;var r=new Image;r.onload=function(){f.setImage(r)},r.src="../file_upload/1.jpg"}),document.body.addEventListener("dragover",function(e){e.stopPropagation(),e.preventDefault()},!1),document.body.addEventListener("drop",c,!1);var l=new FileReader;return f}); -------------------------------------------------------------------------------- /example/static-dist/modules/viewport/viewport.js: -------------------------------------------------------------------------------- 1 | define(["require","qpf","knockout"],function(e){var t=e("qpf"),n=t.use("meta/meta"),r=e("knockout"),i=n.derive(function(){return{tag:"canvas"}},{type:"VIEWPORT",css:"viewport"});return n.provideBinding("viewport",i),i}); -------------------------------------------------------------------------------- /example/static-dist/modules/viewport/viewport.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DRAG AND DROP THE IMAGE

]]> 5 |
6 |
-------------------------------------------------------------------------------- /example/static-dist/preview/amatorka.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/amatorka.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/bleachbypass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/bleachbypass.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/candlelight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/candlelight.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/canny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/canny.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/crispwarm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/crispwarm.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/crispwinter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/crispwinter.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/dropblues.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/dropblues.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/edgyamber.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/edgyamber.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/fallcolors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/fallcolors.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/filmstock_50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/filmstock_50.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/foggynight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/foggynight.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/futuristicbleak.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/futuristicbleak.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/gaussian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/gaussian.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/grayscale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/grayscale.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/horrorblue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/horrorblue.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/latesunset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/latesunset.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/missetikate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/missetikate.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/moonlight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/moonlight.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/nightfromday.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/nightfromday.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/original.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/sepia.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/sepia.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/sketch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/sketch.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/smoothtoon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/smoothtoon.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/sobel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/sobel.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/softelegance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/softelegance.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/softwarming.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/softwarming.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/tealorangepluscontrast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/tealorangepluscontrast.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/tensiongreen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/tensiongreen.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/threshold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/threshold.jpg -------------------------------------------------------------------------------- /example/static-dist/preview/toon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/preview/toon.jpg -------------------------------------------------------------------------------- /example/static-dist/style/imgs/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/arrow-left-active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/arrow-left-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/arrow-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/arrow-right-active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/arrow-right-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/arrow-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/black-Linen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/style/imgs/black-Linen.png -------------------------------------------------------------------------------- /example/static-dist/style/imgs/camera.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/cloud.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/local.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/imgs/picture.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/qpf/images/arrow-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/qpf/images/arrow-up.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static-dist/style/qpf/images/check_radio_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/style/qpf/images/check_radio_sheet.png -------------------------------------------------------------------------------- /example/static-dist/style/qpf/images/link-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/style/qpf/images/link-active.png -------------------------------------------------------------------------------- /example/static-dist/style/qpf/images/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/style/qpf/images/link.png -------------------------------------------------------------------------------- /example/static-dist/style/qpf/images/slider-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static-dist/style/qpf/images/slider-control.png -------------------------------------------------------------------------------- /example/static-dist/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireJS text 2.0.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/requirejs/text for details 5 | */ 6 | 7 | define(["module"],function(e){var t,n,r=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],i=/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,s=/]*>\s*([\s\S]+)\s*<\/body>/im,o=typeof location!="undefined"&&location.href,u=o&&location.protocol&&location.protocol.replace(/\:/,""),a=o&&location.hostname,f=o&&(location.port||undefined),l=[],c=e.config&&e.config()||{};t={version:"2.0.5",strip:function(e){if(e){e=e.replace(i,"");var t=e.match(s);t&&(e=t[1])}else e="";return e},jsEscape:function(e){return e.replace(/(['\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r").replace(/[\u2028]/g,"\\u2028").replace(/[\u2029]/g,"\\u2029")},createXhr:c.createXhr||function(){var e,t,n;if(typeof XMLHttpRequest!="undefined")return new XMLHttpRequest;if(typeof ActiveXObject!="undefined")for(t=0;t<3;t+=1){n=r[t];try{e=new ActiveXObject(n)}catch(i){}if(e){r=[n];break}}return e},parseName:function(e){var t,n,r,i=!1,s=e.indexOf("."),o=e.indexOf("./")===0||e.indexOf("../")===0;return s!==-1&&(!o||s>1)?(t=e.substring(0,s),n=e.substring(s+1,e.length)):t=e,r=n||t,s=r.indexOf("!"),s!==-1&&(i=r.substring(s+1)==="strip",r=r.substring(0,s),n?n=r:t=r),{moduleName:t,ext:n,strip:i}},xdRegExp:/^((\w+)\:)?\/\/([^\/\\]+)/,useXhr:function(e,n,r,i){var s,o,u,a=t.xdRegExp.exec(e);return a?(s=a[2],o=a[3],o=o.split(":"),u=o[1],o=o[0],(!s||s===n)&&(!o||o.toLowerCase()===r.toLowerCase())&&(!u&&!o||u===i)):!0},finishLoad:function(e,n,r,i){r=n?t.strip(r):r,c.isBuild&&(l[e]=r),i(r)},load:function(e,n,r,i){if(i.isBuild&&!i.inlineText){r();return}c.isBuild=i.isBuild;var s=t.parseName(e),l=s.moduleName+(s.ext?"."+s.ext:""),h=n.toUrl(l),p=c.useXhr||t.useXhr;!o||p(h,u,a,f)?t.get(h,function(n){t.finishLoad(e,s.strip,n,r)},function(e){r.error&&r.error(e)}):n([l],function(e){t.finishLoad(s.moduleName+"."+s.ext,s.strip,e,r)})},write:function(e,n,r,i){if(l.hasOwnProperty(n)){var s=t.jsEscape(l[n]);r.asModule(e+"!"+n,"define(function () { return '"+s+"';});\n")}},writeFile:function(e,n,r,i,s){var o=t.parseName(n),u=o.ext?"."+o.ext:"",a=o.moduleName+u,f=r.toUrl(o.moduleName+u)+".js";t.load(a,r,function(n){var r=function(e){return i(f,e)};r.asModule=function(e,t){return i.asModule(e,f,t)},t.write(e,a,r,s)},s)}};if(c.env==="node"||!c.env&&typeof process!="undefined"&&process.versions&&!!process.versions.node)n=require.nodeRequire("fs"),t.get=function(e,t){var r=n.readFileSync(e,"utf8");r.indexOf("")===0&&(r=r.substring(1)),t(r)};else if(c.env==="xhr"||!c.env&&t.createXhr())t.get=function(e,n,r,i){var s=t.createXhr(),o;s.open("GET",e,!0);if(i)for(o in i)i.hasOwnProperty(o)&&s.setRequestHeader(o.toLowerCase(),i[o]);c.onXhr&&c.onXhr(s,e),s.onreadystatechange=function(t){var i,o;s.readyState===4&&(i=s.status,i>399&&i<600?(o=new Error(e+" HTTP status: "+i),o.xhr=s,r(o)):n(s.responseText))},s.send(null)};else if(c.env==="rhino"||!c.env&&typeof Packages!="undefined"&&typeof java!="undefined")t.get=function(e,t){var n,r,i="utf-8",s=new java.io.File(e),o=java.lang.System.getProperty("line.separator"),u=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(s),i)),a="";try{n=new java.lang.StringBuffer,r=u.readLine(),r&&r.length()&&r.charAt(0)===65279&&(r=r.substring(1)),n.append(r);while((r=u.readLine())!==null)n.append(o),n.append(r);a=String(n.toString())}finally{u.close()}t(a)};return t}); -------------------------------------------------------------------------------- /example/static/app.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var _ = require("_"); 5 | 6 | var appXML = require("text!modules/app.xml"); 7 | var router = require("modules/router"); 8 | var controllerConfig = require("./controllerConfig"); 9 | var Event = qpf.use("core/mixin/event"); 10 | 11 | // Dependencies 12 | require("modules/common/histogram"); 13 | require("modules/common/list"); 14 | require("modules/common/modal"); 15 | require("modules/common/region"); 16 | require("modules/common/iconbutton"); 17 | require("modules/common/nativehtml"); 18 | 19 | function start(){ 20 | var ko = require("knockout"); 21 | var XMLParser = qpf.use("core/xmlparser"); 22 | 23 | var dom = XMLParser.parse(appXML); 24 | 25 | document.body.appendChild( dom ); 26 | 27 | ko.applyBindings(controllerConfig, dom); 28 | 29 | router.init("/"); 30 | } 31 | 32 | var app = { 33 | 34 | start : start 35 | 36 | } 37 | 38 | _.extend(app, Event); 39 | 40 | return app; 41 | }) -------------------------------------------------------------------------------- /example/static/boot.js: -------------------------------------------------------------------------------- 1 | /** 2 | * boot the web app 3 | */ 4 | (function(){ 5 | //========================= 6 | // CONFIG 7 | //========================= 8 | 9 | $LAB.setGlobalDefaults({BasePath:'lib/'}); 10 | //========================= 11 | // Load Library 12 | //========================= 13 | $LAB.script("require.js") 14 | .script("director.js") 15 | .wait(boot); 16 | 17 | //======================== 18 | // Load Main Module 19 | //======================== 20 | function boot(){ 21 | 22 | config(); 23 | 24 | require(["app"], function(app){ 25 | app.start(); 26 | }) 27 | } 28 | 29 | 30 | function config(){ 31 | 32 | requirejs.config({ 33 | paths : { 34 | async : "lib/async", 35 | qpf : "lib/qpf", 36 | emage : "lib/emage", 37 | knockout : "lib/knockout", 38 | // Use jquery temporary, zepto's bind does not support context 39 | "$" : "lib/jquery", 40 | "_" : "lib/underscore" 41 | }, 42 | shim : { 43 | '$' : { 44 | exports : "$" 45 | }, 46 | '_' : { 47 | exports : "_" 48 | }, 49 | 'app' :["modules/common/histogram", 50 | "modules/common/list", 51 | "modules/common/modal", 52 | "modules/common/region", 53 | "modules/common/iconbutton", 54 | "modules/common/nativehtml"] 55 | }, 56 | }) 57 | } 58 | 59 | }).call( this ) -------------------------------------------------------------------------------- /example/static/controllerConfig.js: -------------------------------------------------------------------------------- 1 | // controller defines how and when the modules are loaded 2 | // todo : add priority?? 3 | define({ 4 | //---------region: main navigator------------- 5 | "navigator" : { 6 | "modules/navigator/index" : { 7 | "url" : "*" 8 | } 9 | }, 10 | "viewport" : { 11 | "modules/viewport/index" : { 12 | "url" : "*" 13 | } 14 | }, 15 | "filters" : { 16 | "modules/filters/index" : { 17 | "url" : "*" 18 | } 19 | }, 20 | "imageList" : { 21 | "modules/imagelist/index" : { 22 | "url" : "*" 23 | } 24 | } 25 | }) -------------------------------------------------------------------------------- /example/static/index-dist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EMAGE 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /example/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | EMAGE 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/static/lut/amatorka.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/amatorka.png -------------------------------------------------------------------------------- /example/static/lut/bleachbypass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/bleachbypass.png -------------------------------------------------------------------------------- /example/static/lut/candlelight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/candlelight.png -------------------------------------------------------------------------------- /example/static/lut/crispwarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/crispwarm.png -------------------------------------------------------------------------------- /example/static/lut/crispwinter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/crispwinter.png -------------------------------------------------------------------------------- /example/static/lut/dropblues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/dropblues.png -------------------------------------------------------------------------------- /example/static/lut/edgyamber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/edgyamber.png -------------------------------------------------------------------------------- /example/static/lut/fallcolors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/fallcolors.png -------------------------------------------------------------------------------- /example/static/lut/filmstock_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/filmstock_50.png -------------------------------------------------------------------------------- /example/static/lut/foggynight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/foggynight.png -------------------------------------------------------------------------------- /example/static/lut/futuristicbleak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/futuristicbleak.png -------------------------------------------------------------------------------- /example/static/lut/horrorblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/horrorblue.png -------------------------------------------------------------------------------- /example/static/lut/latesunset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/latesunset.png -------------------------------------------------------------------------------- /example/static/lut/lookup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/lookup.png -------------------------------------------------------------------------------- /example/static/lut/missetikate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/missetikate.png -------------------------------------------------------------------------------- /example/static/lut/moonlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/moonlight.png -------------------------------------------------------------------------------- /example/static/lut/nightfromday.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/nightfromday.png -------------------------------------------------------------------------------- /example/static/lut/soft_elegance_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/soft_elegance_1.png -------------------------------------------------------------------------------- /example/static/lut/soft_elegance_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/soft_elegance_2.png -------------------------------------------------------------------------------- /example/static/lut/softwarming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/softwarming.png -------------------------------------------------------------------------------- /example/static/lut/tealorangepluscontrast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/tealorangepluscontrast.png -------------------------------------------------------------------------------- /example/static/lut/tensiongreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/lut/tensiongreen.png -------------------------------------------------------------------------------- /example/static/modules/app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/static/modules/common/iconbutton.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var Button = qpf.use("meta/button"); 5 | var Meta = qpf.use("meta/meta"); 6 | var ko = require("knockout"); 7 | 8 | var IconButton = Button.derive(function(){ 9 | return { 10 | $el : $("
"), 11 | icon : ko.observable("") 12 | } 13 | }, { 14 | type : "ICONBUTTON", 15 | css : _.union("icon-button", Button.prototype.css), 16 | 17 | template : '
', 18 | }) 19 | 20 | Meta.provideBinding("iconbutton", IconButton); 21 | 22 | return IconButton; 23 | 24 | }) -------------------------------------------------------------------------------- /example/static/modules/common/list.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var listItem = require("./listitem"); 5 | var Container = qpf.use("container/container"); 6 | var ko = require("knockout"); 7 | 8 | var List = Container.derive(function(){ 9 | 10 | return { 11 | 12 | dataSource : ko.observableArray([]), 13 | 14 | itemView : ko.observable(listItem), // item component constructor 15 | 16 | selected : ko.observable() 17 | } 18 | }, { 19 | type : "LIST", 20 | 21 | css : "list", 22 | 23 | template : '
\ 24 |
\ 25 |
\ 26 |
\ 27 |
', 28 | 29 | initialize : function(){ 30 | 31 | var oldArray = _.clone( this.dataSource() ), 32 | self = this; 33 | 34 | this.dataSource.subscribe(function(newArray){ 35 | this._update(oldArray, newArray); 36 | oldArray = _.clone( newArray ); 37 | _.each(oldArray, function(item, idx){ 38 | if( ko.utils.unwrapObservable(item.selected) ){ 39 | this.selected(idx) 40 | } 41 | }, this); 42 | }, this); 43 | 44 | this.selected.subscribe(function(idx){ 45 | this._unSelectAll(); 46 | var child = this.children()[idx]; 47 | child && 48 | child.$el.addClass("selected"); 49 | }, this); 50 | 51 | this.$el.delegate(".qpf-container-item", "click", function(){ 52 | var context = ko.contextFor( this); 53 | self.selected( context.$index() ); 54 | }) 55 | 56 | this._update([], oldArray); 57 | }, 58 | 59 | _update : function(oldArray, newArray){ 60 | 61 | var children = this.children(); 62 | var ItemView = this.itemView(); 63 | var result = []; 64 | 65 | var differences = ko.utils.compareArrays(oldArray, newArray); 66 | var newChildren = []; 67 | _.each(differences, function(item){ 68 | if( item.status === "retained"){ 69 | var index = oldArray.indexOf(item.value); 70 | result[ index ] = children[ index ]; 71 | }else if( item.status === "added"){ 72 | var newChild = new ItemView({ 73 | attributes : item.value 74 | }); 75 | result[item.index] = newChild; 76 | children.splice(item.index, 0, newChild); 77 | newChildren.push(newChild); 78 | } 79 | }, this); 80 | this.children( result ); 81 | // render after it is appended in the dom 82 | // so the component like range will be resized proply 83 | _.each(newChildren, function(c){ 84 | c.render(); 85 | }) 86 | }, 87 | 88 | _unSelectAll : function(){ 89 | _.each(this.children(), function(child, idx){ 90 | child.$el.removeClass("selected") 91 | }, this) 92 | } 93 | 94 | }) 95 | 96 | Container.provideBinding("list", List); 97 | 98 | return List; 99 | }) -------------------------------------------------------------------------------- /example/static/modules/common/listitem.js: -------------------------------------------------------------------------------- 1 | // default list item component 2 | define(function(require){ 3 | 4 | var qpf = require("qpf"); 5 | var Meta = qpf.use("meta/meta"); 6 | var ko = require("knockout"); 7 | 8 | var ListItem = Meta.derive(function(){ 9 | 10 | return { 11 | title : ko.observable(""), 12 | icon : ko.observable(""), 13 | href : ko.observable(""), 14 | } 15 | }, { 16 | type : "LISTITEM", 17 | 18 | css : "list-item", 19 | 20 | initialize : function(){ 21 | this.$el.mousedown(function(e){ 22 | e.preventDefault(); 23 | }) 24 | 25 | var self = this; 26 | this.$el.click(function(){ 27 | var href = self.href(); 28 | if(href && href.indexOf("#") == 0){ 29 | window.location.hash = href; 30 | } 31 | }) 32 | }, 33 | 34 | template : '
\ 35 |
' 36 | }) 37 | 38 | return ListItem; 39 | }) -------------------------------------------------------------------------------- /example/static/modules/common/modal.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var Clazz = qpf.use("core/clazz"); 5 | var Window = qpf.use("container/window"); 6 | var Container = qpf.use("container/container"); 7 | var Inline = qpf.use("container/inline"); 8 | var Button = qpf.use("meta/button"); 9 | var ko = require("knockout"); 10 | 11 | var wind = new Window({ 12 | attributes : { 13 | class : "qpf-modal" 14 | } 15 | }), 16 | body = new Container, 17 | buttons = new Inline, 18 | applyButton = new Button({ 19 | attributes : { 20 | text : "确 定" 21 | } 22 | }), 23 | cancelButton = new Button({ 24 | attributes : { 25 | text : "取 消" 26 | } 27 | }); 28 | wind.add(body); 29 | wind.add(buttons); 30 | buttons.add(applyButton); 31 | buttons.add(cancelButton); 32 | 33 | wind.render(); 34 | document.body.appendChild(wind.$el[0]); 35 | var $mask = $('
'); 36 | document.body.appendChild($mask[0]); 37 | 38 | wind.$el.hide(); 39 | $mask.hide(); 40 | var Modal = Clazz.derive(function(){ 41 | return { 42 | title : "", 43 | 44 | body : null, 45 | onApply : function(next){next()}, 46 | onCancel : function(next){next()} 47 | } 48 | }, { 49 | show : function(){ 50 | var self = this; 51 | wind.title( this.title); 52 | 53 | body.removeAll(); 54 | this.body && 55 | body.add(this.body); 56 | 57 | applyButton.off("click"); 58 | cancelButton.off("click"); 59 | applyButton.on("click", function(){ 60 | self.onApply( self.hide ) 61 | }); 62 | cancelButton.on("click", function(){ 63 | self.onCancel( self.hide ); 64 | }); 65 | 66 | wind.$el.show(); 67 | $mask.show(); 68 | 69 | wind.left( ( $(window).width() - wind.$el.width() )/2 ) 70 | wind.top( ( $(window).height() - wind.$el.height() )/2-100 ) 71 | }, 72 | hide : function(){ 73 | wind.$el.hide(); 74 | $mask.hide(); 75 | } 76 | }) 77 | 78 | Modal.popup = function(title, body, onApply, onCancel){ 79 | var modal = new Modal({ 80 | title : title, 81 | body : body, 82 | onApply : onApply || function(next){next()}, 83 | onCancel : onCancel || function(next){next()} 84 | }); 85 | modal.body.render(); 86 | modal.show(); 87 | } 88 | 89 | Modal.confirm = function(title, text, onApply, onCancel){ 90 | var modal = new Modal({ 91 | title : title, 92 | //TODO: Implement a componennt like

? 93 | body : new Label({ 94 | attributes : { 95 | text : text 96 | }, 97 | temporary : true 98 | }), 99 | onApply : onApply || function(next){next()}, 100 | onCancel : onCancel || function(next){next()} 101 | }); 102 | modal.body.render(); 103 | modal.show(); 104 | } 105 | 106 | return Modal; 107 | }) -------------------------------------------------------------------------------- /example/static/modules/common/nativehtml.js: -------------------------------------------------------------------------------- 1 | // default list item component 2 | define(function(require){ 3 | 4 | var qpf = require("qpf"); 5 | var Meta = qpf.use("meta/meta"); 6 | var ko = require("knockout"); 7 | var XMLParser = qpf.use("core/xmlparser"); 8 | var _ = require("_"); 9 | 10 | var NativeHtml = Meta.derive(function(){ 11 | 12 | return { 13 | $el : $('

'), 14 | html : ko.observable("ko") 15 | } 16 | }, { 17 | type : "NATIVEHTML", 18 | 19 | css : "native-html" 20 | }) 21 | 22 | Meta.provideBinding("nativehtml", NativeHtml); 23 | 24 | XMLParser.provideParser("nativehtml", function(xmlNode){ 25 | var children = XMLParser.util.getChildren(xmlNode); 26 | var html = ""; 27 | _.each(children, function(child){ 28 | // CDATA 29 | if(child.nodeType === 4){ 30 | html += child.textContent; 31 | } 32 | }); 33 | if( html ){ 34 | return { 35 | html : html 36 | } 37 | } 38 | }) 39 | 40 | return NativeHtml; 41 | }) -------------------------------------------------------------------------------- /example/static/modules/common/region.js: -------------------------------------------------------------------------------- 1 | // Application will have specificated layout 2 | // And each part in the layout is called Region 3 | // Region will manage how the modules under it is load and unload 4 | 5 | define(function(require){ 6 | 7 | var qpf = require("qpf"); 8 | var Meta = qpf.use("meta/meta"); 9 | var Base = qpf.use("base"); 10 | var ko = require("knockout"); 11 | var _ = require("_") 12 | 13 | var router = require("../router"); 14 | 15 | var Region = Base.derive(function(){ 16 | // Example of controller config 17 | //{ 18 | // "modules/moduleConfig/index" : { 19 | // "url" : ""/methods/:page/:module:/config", 20 | // "context" : ["page", "module"] 21 | // } 22 | return { 23 | controller : {}, 24 | 25 | _moduleCache : {}, 26 | 27 | _currentModule : null 28 | } 29 | }, { 30 | 31 | type : "REGION", 32 | 33 | css : "region", 34 | 35 | initialize : function(){ 36 | var self = this; 37 | _.each(this.controller, function(config, modulePath){ 38 | var url = config.url, 39 | context = config.context; 40 | if( url ==="*"){ 41 | self.enterModule(modulePath, {}, function(){}); 42 | }else{ 43 | router.on("after", url, self.leaveModule.bind(self, modulePath) ); 44 | router.on( url, self.enterModule.bind(self, modulePath, context) ); 45 | } 46 | }) 47 | // router.on( "/", self._updateStatus.bind(self) ); 48 | }, 49 | 50 | _updateStatus : function(){ 51 | var self = this; 52 | var next = Array.prototype.pop.call(arguments); 53 | // put it in next tick after the enter module event is executed; 54 | var cacheSize = 0; 55 | _.each(self._moduleCache, function(module){ 56 | cacheSize++; 57 | if( module.__enable__ ){ 58 | module.enable( next ); 59 | }else{ 60 | module.disable( next ); 61 | } 62 | }) 63 | if( ! cacheSize){ 64 | next() 65 | } 66 | }, 67 | 68 | leaveModule : function(modulePath){ 69 | var module = this._moduleCache[modulePath]; 70 | var next = Array.prototype.pop.call(arguments); 71 | 72 | if( module ){ 73 | // mark as disable 74 | // real enable and disable will be executed 75 | // batchly in the _updateStatus 76 | // module.__enable__ = false; 77 | module.disable( next ); 78 | } 79 | }, 80 | 81 | enterModule : function(modulePath, contextFields){ 82 | var context = {}; 83 | var self = this; 84 | var next = Array.prototype.pop.call(arguments); 85 | 86 | var params = Array.prototype.slice.call(arguments, 2); 87 | 88 | if( contextFields ){ 89 | _.each(params, function(param, idx){ 90 | var field = contextFields[idx]; 91 | if( field ){ 92 | context[field] = param; 93 | } 94 | }) 95 | } 96 | var module = this._moduleCache[modulePath]; 97 | 98 | if( ! module){ 99 | require([modulePath], function(module){ 100 | if( module && module.start){ 101 | 102 | var $el = module.start( ); 103 | if( $el ){ 104 | // Append after application resize finished 105 | // In case the module is in cache and loaded immediately 106 | // _.defer(function(){ 107 | self.$el.append( $el ); 108 | // }) 109 | } 110 | module.mainComponent.parent = self; 111 | // module.__enable__ = true; 112 | module.enable( next ) 113 | module.setContext(context); 114 | 115 | self._moduleCache[modulePath] = module; 116 | self._currentModule = module; 117 | self.onResize(); 118 | } 119 | }) 120 | }else{ 121 | // module.__enable__ = true; 122 | module.enable( next ) 123 | module.setContext(context); 124 | 125 | this._currentModule = module; 126 | this.onResize(); 127 | } 128 | 129 | next(); 130 | }, 131 | 132 | onResize : function(){ 133 | if( this._currentModule && this._currentModule.mainComponent){ 134 | this._currentModule.mainComponent.width( this.$el.width() ); 135 | this._currentModule.mainComponent.height( this.$el.height() ); 136 | } 137 | Base.prototype.onResize.call(this); 138 | 139 | } 140 | }) 141 | 142 | Meta.provideBinding("region", Region); 143 | 144 | return Region; 145 | }) -------------------------------------------------------------------------------- /example/static/modules/filters/filter.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |
8 |
-------------------------------------------------------------------------------- /example/static/modules/filters/filter.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | var qpf = require("qpf"); 3 | var Widget = qpf.use("widget/widget"); 4 | var ko = require("knockout"); 5 | var filterHTML = require("text!./filter.html"); 6 | var viewport = require("../viewport/index"); 7 | 8 | var Filter = Widget.derive(function(){ 9 | 10 | var viewModel = { 11 | title : ko.observable(""), 12 | preview: ko.observable(""), 13 | description : ko.observable(""), 14 | 15 | // filter name will be used in finding the fx 16 | name : ko.observable(""), 17 | // parameters will be set in the filterLayer 18 | parameters : ko.observable({}), 19 | 20 | use : function(){ 21 | viewport.filterLayer.use(this.name()); 22 | var parameters = this.parameters(); 23 | 24 | var deferredUpdate = false; 25 | if(parameters){ 26 | viewport.filterLayer.set(parameters); 27 | 28 | var isLoading = 0; 29 | for(var name in parameters){ 30 | if(parameters[name] instanceof Image){ 31 | var img = parameters[name]; 32 | if( ! img.complete){ 33 | deferredUpdate = true; 34 | isLoading++; 35 | img.onload = function(){ 36 | isLoading--; 37 | if(isLoading == 0){ 38 | viewport.update(); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | if( ! deferredUpdate){ 46 | viewport.update(); 47 | } 48 | } 49 | } 50 | 51 | viewModel._previewSrc = ko.computed(function(){ 52 | if( viewModel.preview() ){ 53 | return viewModel.preview() 54 | } 55 | }) 56 | return viewModel; 57 | }, { 58 | 59 | type : "FILTER", 60 | css : "filter", 61 | 62 | template : filterHTML 63 | }); 64 | 65 | return Filter; 66 | }) -------------------------------------------------------------------------------- /example/static/modules/filters/filters.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/static/modules/filters/index.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var Module = require("../module"); 4 | var xml = require("text!./filters.xml"); 5 | var qpf = require("qpf"); 6 | var FilterView = require("./filter"); 7 | var dataSource = require("./source"); 8 | var viewport = require("../viewport/index"); 9 | var _ = require("_"); 10 | 11 | var ko = require('knockout'); 12 | 13 | var filters = new Module({ 14 | name : "filters", 15 | xml : xml, 16 | 17 | filters : ko.observableArray( dataSource.filters ), 18 | FilterView : FilterView, 19 | 20 | seachKeyword : ko.observable(""), 21 | 22 | colorAdjust : { 23 | brightness : ko.observable(0), 24 | contrast : ko.observable(1), 25 | exposure : ko.observable(0), 26 | gamma : ko.observable(1), 27 | saturation : ko.observable(1) 28 | }, 29 | hue : ko.observable(0) 30 | }); 31 | 32 | var histogram; 33 | filters.on("start", function(){ 34 | histogram = filters.mainComponent.$el.find("#Histogram").qpf("get")[0]; 35 | histogram.image = viewport.processor.canvas; 36 | histogram.update(); 37 | histogram.refresh(); 38 | }) 39 | 40 | ko.computed(function(){ 41 | viewport.colorAdjustLayer.set({ 42 | "brightness" : filters.colorAdjust.brightness(), 43 | "contrast" : filters.colorAdjust.contrast(), 44 | "exposure" : filters.colorAdjust.exposure(), 45 | "gamma" : filters.colorAdjust.gamma(), 46 | "saturation" : filters.colorAdjust.saturation() 47 | }); 48 | 49 | viewport.hueLayer.set("hue", filters.hue()); 50 | viewport.update(); 51 | }) 52 | viewport.on("update", function(){ 53 | histogram.update(); 54 | histogram.refresh(); 55 | }) 56 | 57 | filters.seachKeyword.subscribe(function(newValue){ 58 | if( ! newValue ){ 59 | filters.filters( dataSource.filters ); 60 | }else{ 61 | filters.filters( _.filter(filters.filters(), function(value){ 62 | return value.name.indexOf( newValue.toLowerCase() ) >= 0 || 63 | value.title.indexOf( newValue )>=0; 64 | }) ) 65 | } 66 | }) 67 | 68 | return filters; 69 | }) -------------------------------------------------------------------------------- /example/static/modules/imagelist/imageitem.js: -------------------------------------------------------------------------------- 1 | // default list item component 2 | define(function(require){ 3 | 4 | var qpf = require("qpf"); 5 | var Meta = qpf.use("meta/meta"); 6 | var ko = require("knockout"); 7 | 8 | var ListItem = Meta.derive(function(){ 9 | 10 | return { 11 | title : ko.observable(""), 12 | thumb : ko.observable(""), 13 | url : ko.observable(), 14 | } 15 | }, { 16 | type : "IMAGEITEM", 17 | 18 | css : "image-item", 19 | 20 | initialize : function(){ 21 | this.$el.mousedown(function(e){ 22 | e.preventDefault(); 23 | }) 24 | }, 25 | 26 | template : '
' 27 | }) 28 | 29 | 30 | ko.bindingHandlers["qpf_image"] = { 31 | init : function(element, valueAccessor){ 32 | element.innerHTML = ""; 33 | var image = ko.utils.unwrapObservable( valueAccessor() ); 34 | if(typeof image === "string"){ 35 | var img = document.createElement("img"); 36 | img.src = image; 37 | }else{ 38 | var img = image; 39 | } 40 | element.appendChild( img ); 41 | } 42 | } 43 | return ListItem; 44 | }) -------------------------------------------------------------------------------- /example/static/modules/imagelist/imagelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/static/modules/imagelist/index.js: -------------------------------------------------------------------------------- 1 | define( function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var ko = require("knockout"); 5 | var Module = require("../module"); 6 | var xml = require("text!./imagelist.xml"); 7 | 8 | var List = require("../common/list"); 9 | var ImageItem = require("./imageitem"); 10 | 11 | var viewport = require("../viewport/index"); 12 | 13 | var imageList = new Module({ 14 | name : "imagelist", 15 | xml : xml, 16 | 17 | images : ko.observableArray(), 18 | ImageItem : ImageItem 19 | }) 20 | var listData, 21 | page = 0, 22 | pageLength = 5, 23 | maxPage; 24 | $.get("../file_upload/list.json", function(data){ 25 | listData = data; 26 | maxPage = Math.floor(listData.length / pageLength-0.00001); 27 | imageList.images( listData.slice(0, pageLength) ); 28 | }) 29 | 30 | var img; 31 | imageList.$el.delegate(".qpf-ui-image-item", "click", function(){ 32 | var thumb = $(this).find("img")[0]; 33 | viewport.setImage( thumb ); 34 | 35 | img = new Image; 36 | img.onload = function(){ 37 | viewport.setImage( img ); 38 | } 39 | img.src = $(this).qpf('get')[0].url(); 40 | }) 41 | .delegate('.button-left', 'click', prevPage) 42 | .delegate('.button-right', 'click', nextPage); 43 | 44 | function prevPage(){ 45 | page = Math.max(0, page-1); 46 | imageList.images( listData.slice( page*pageLength, Math.min(listData.length, (page+1)*pageLength) ) ); 47 | } 48 | 49 | function nextPage(){ 50 | page = Math.min( page+1, maxPage); 51 | imageList.images( listData.slice( page*pageLength, Math.min(listData.length, (page+1)*pageLength) ) ); 52 | } 53 | 54 | return imageList 55 | } ) -------------------------------------------------------------------------------- /example/static/modules/module.js: -------------------------------------------------------------------------------- 1 | //============================================= 2 | // Constructor of module 3 | // module can be inited from xml, 4 | // and it will only get the first component as a 5 | // container, 6 | //============================================= 7 | define(function(require){ 8 | 9 | var qpf = require("qpf"); 10 | var Base = qpf.use("base"); 11 | var ko = require("knockout"); 12 | var XMLParser = qpf.use("core/xmlparser"); 13 | var Derive = qpf.use("core/mixin/derive"); 14 | var Event = qpf.use("core/mixin/event"); 15 | 16 | var clazz = new Function(); 17 | _.extend(clazz, Derive); 18 | _.extend(clazz.prototype, Event); 19 | 20 | var Module = clazz.derive(function(){ 21 | return { 22 | name : "", 23 | $el : $("
"), 24 | xml : "", 25 | context : {}, 26 | 27 | mainComponent : null 28 | } 29 | }, { 30 | start : function( ){ 31 | if( this.xml ){ 32 | this.applyXML(this.xml); 33 | }; 34 | 35 | this.trigger("start"); 36 | return this.$el; 37 | }, 38 | 39 | enable : function(next){ 40 | this.$el.show(); 41 | 42 | this.trigger("enable"); 43 | 44 | next && next(); 45 | }, 46 | 47 | disable : function(next){ 48 | this.$el.hide(); 49 | 50 | this.trigger("disable") 51 | next && next(); 52 | }, 53 | 54 | setContext : function(context){ 55 | // save default context 56 | if( ! this._defaultContext){ 57 | this._defaultContext = {}; 58 | _.each(this.context, function(value, name){ 59 | this._defaultContext[name] = value(); 60 | }, this) 61 | } 62 | for(var name in this.context){ 63 | if( typeof(context[name]) !== "undefined" ){ 64 | this.context[name]( context[name] ); 65 | }else{ 66 | this.context[name]( this._defaultContext[name] ); 67 | } 68 | } 69 | Base.prototype._mappingAttributes.call(this.context, context, true); 70 | }, 71 | 72 | dispose : function(){ 73 | Base.disposeByDom(this.$el[0]); 74 | this.$el.remove(); 75 | }, 76 | 77 | loadingStart : function(){ 78 | if( this._$mask){ 79 | this._$mask.addClass("loading").show(); 80 | } 81 | }, 82 | 83 | loadingEnd : function(){ 84 | if(this._$mask){ 85 | this._$mask.removeClass("loading").hide(); 86 | } 87 | }, 88 | 89 | applyXML : function(xml){ 90 | XMLParser.parse(xml, this.$el[0] ); 91 | ko.applyBindings(this, this.$el[0]); 92 | 93 | var firstChild = this.$el[0].firstChild; 94 | if( firstChild ){ 95 | this.mainComponent = Base.getByDom(firstChild); 96 | } 97 | } 98 | }) 99 | return Module; 100 | }) -------------------------------------------------------------------------------- /example/static/modules/navigator/imageitem.js: -------------------------------------------------------------------------------- 1 | // default list item component 2 | define(function(require){ 3 | 4 | var qpf = require("qpf"); 5 | var Meta = qpf.use("meta/meta"); 6 | var ko = require("knockout"); 7 | 8 | var ListItem = Meta.derive(function(){ 9 | 10 | return { 11 | title : ko.observable(""), 12 | image : ko.observable(""), 13 | } 14 | }, { 15 | type : "IMAGEITEM", 16 | 17 | css : "image-item", 18 | 19 | initialize : function(){ 20 | this.$el.mousedown(function(e){ 21 | e.preventDefault(); 22 | }) 23 | }, 24 | 25 | template : '
' 26 | }) 27 | 28 | 29 | ko.bindingHandlers["qpf_image"] = { 30 | init : function(element, valueAccessor){ 31 | element.innerHTML = ""; 32 | var image = ko.utils.unwrapObservable( valueAccessor() ); 33 | if(typeof image === "string"){ 34 | var img = document.createElement("img"); 35 | img.src = image; 36 | }else{ 37 | var img = image; 38 | } 39 | element.appendChild( img ); 40 | } 41 | } 42 | return ListItem; 43 | }) -------------------------------------------------------------------------------- /example/static/modules/navigator/index.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var ko = require("knockout"); 5 | var Module = require("../module"); 6 | var xml = require("text!./navigator.xml"); 7 | var NavLink = require("./navlink"); 8 | 9 | var viewport = require("../viewport/index"); 10 | var router = require("../router"); 11 | 12 | var nav = new Module({ 13 | name : "navigator", 14 | xml : xml 15 | }); 16 | 17 | nav.$el.delegate(".qpf-ui-navlink", "click", function(){ 18 | var $this= $(this), 19 | navlink = $this.qpf("get")[0]; 20 | if( navlink ){ 21 | switch(navlink.icon()){ 22 | case "camera": 23 | // switchToCamera(); 24 | break; 25 | case "cloud": 26 | // switchToCloud(); 27 | } 28 | } 29 | nav.$el.find(".qpf-ui-navlink").removeClass("active"); 30 | $this.addClass("active"); 31 | }) 32 | var video; 33 | 34 | function switchToCamera(){ 35 | viewport.on("beforerender", function(){ 36 | tex.needsUpdate = true; 37 | }) 38 | var videoObj = { 39 | video : true 40 | } 41 | // use camera 42 | if(navigator.getUserMedia) { // Standard 43 | navigator.getUserMedia(videoObj, function(stream) { 44 | video.src = stream; 45 | video.play(); 46 | }, errBack); 47 | } else if(navigator.webkitGetUserMedia) { // WebKit-prefixed 48 | navigator.webkitGetUserMedia(videoObj, function(stream){ 49 | video.src = window.webkitURL.createObjectURL(stream); 50 | video.play(); 51 | }, errBack); 52 | }; 53 | function errBack(){ 54 | console.log(arguments); 55 | } 56 | } 57 | 58 | return nav; 59 | }) -------------------------------------------------------------------------------- /example/static/modules/navigator/navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/static/modules/navigator/navlink.js: -------------------------------------------------------------------------------- 1 | define(function(){ 2 | 3 | var qpf = require("qpf"); 4 | var Meta = qpf.use("meta/meta"); 5 | var ko = require("knockout"); 6 | 7 | var NavLink = Meta.derive(function(){ 8 | 9 | return { 10 | icon : ko.observable(), 11 | title : ko.observable(""), 12 | href : ko.observable("") 13 | } 14 | }, { 15 | type : "NAVLINK", 16 | 17 | css : "navlink", 18 | 19 | initialize : function(){ 20 | var self = this; 21 | this.$el.click(function(e){ 22 | window.location.hash = '#/' + self.href() 23 | }) 24 | }, 25 | 26 | template : '
\ 27 |
' 28 | }) 29 | 30 | Meta.provideBinding("navlink", NavLink); 31 | 32 | return NavLink; 33 | }) -------------------------------------------------------------------------------- /example/static/modules/router.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var router = Router(); 4 | 5 | router.configure({ 6 | recurse : "forward" 7 | }) 8 | 9 | return router; 10 | }) -------------------------------------------------------------------------------- /example/static/modules/viewport/index.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var Module = require("../module"); 4 | var xml = require("text!./viewport.xml"); 5 | var Viewport = require("./viewport"); 6 | 7 | var qpf = require("qpf"); 8 | var ko = require("knockout"); 9 | var $ = require("$"); 10 | var emage = require("emage"); 11 | 12 | var _ = require("_"); 13 | 14 | var viewport = new Module({ 15 | name : "viewport", 16 | xml : xml, 17 | 18 | applyFilter : ko.observable(true), 19 | 20 | resize : function(){ 21 | 22 | if( viewport.mainComponent && 23 | viewport.mainComponent.parent && 24 | this.processor.image ){ 25 | 26 | var img = this.processor.image; 27 | var ratio = img.height/img.width; 28 | 29 | var main = viewport.mainComponent; 30 | var maxWidth = main.parent.width(); 31 | var maxHeight = main.parent.height(); 32 | // resize 33 | if( ratio < 1){ 34 | main.$el.css({ 35 | "margin-top" : (maxHeight - maxWidth*ratio)/2+"px", 36 | "margin-left" : "0px" 37 | } ); 38 | main.height( maxWidth*ratio ); 39 | main.width( maxWidth ); 40 | }else{ 41 | main.$el.css({ 42 | "margin-left" : (maxWidth - maxHeight/ratio)/2, 43 | "margin-top" : "0px" 44 | }); 45 | main.width( maxHeight/ratio ); 46 | main.height( maxHeight ); 47 | } 48 | } 49 | }, 50 | 51 | onResize : function(){ 52 | viewport.resize(); 53 | }, 54 | 55 | setImage : function(img){ 56 | this.processor.image = img; 57 | this.update(); 58 | this.resize(); 59 | }, 60 | update : _.throttle(function(){ 61 | // If the image is loaded; 62 | if(viewport.processor.image){ 63 | viewport.processor.update(); 64 | this.trigger("update"); 65 | } 66 | }, 100), 67 | 68 | processor : new emage.Processor(), 69 | 70 | loadImageFromFile : loadImageFromFile, 71 | 72 | colorAdjustLayer : null, 73 | hueLayer : null, 74 | filterLayer : null 75 | }); 76 | 77 | viewport.on("start", function(){ 78 | viewport.mainComponent.$el.find("canvas").replaceWith(this.processor.canvas); 79 | 80 | var filterLayer = new emage.Layer(); 81 | viewport.processor.add(filterLayer); 82 | var colorAdjustLayer = new emage.Layer("buildin.coloradjust"); 83 | var hueLayer = new emage.Layer("buildin.hue"); 84 | viewport.processor.add(colorAdjustLayer); 85 | viewport.processor.add(hueLayer); 86 | 87 | this.colorAdjustLayer = colorAdjustLayer; 88 | this.filterLayer = filterLayer; 89 | this.hueLayer = hueLayer; 90 | 91 | // viewport.setImage('../file_upload/thumb/1.jpg'); 92 | var img = new Image(); 93 | img.onload = function(){ 94 | viewport.setImage( img ); 95 | } 96 | img.src = '../file_upload/1.jpg'; 97 | 98 | }); 99 | 100 | document.body.addEventListener("dragover", function(e){ 101 | e.stopPropagation(); 102 | e.preventDefault(); 103 | }, false); 104 | document.body.addEventListener("drop", handleDrop, false); 105 | 106 | var imageReader = new FileReader(); 107 | function handleDrop(e){ 108 | e.stopPropagation(); 109 | e.preventDefault(); 110 | var file = e.dataTransfer.files[0]; 111 | if(file && file.type.match(/image/)){ 112 | loadImageFromFile(file); 113 | } 114 | } 115 | 116 | function loadImageFromFile(file){ 117 | imageReader.onload = function(e){ 118 | var img = new Image(); 119 | imageReader.onload = null; 120 | 121 | img.onload = function(){ 122 | img.onload = null; 123 | viewport.setImage(img); 124 | 125 | // remove the hint 126 | viewport.mainComponent.$el.find(".draghint").remove(); 127 | } 128 | img.src = e.target.result; 129 | } 130 | imageReader.readAsDataURL(file); 131 | } 132 | 133 | 134 | return viewport; 135 | }) -------------------------------------------------------------------------------- /example/static/modules/viewport/viewport.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qpf = require("qpf"); 4 | var Meta = qpf.use("meta/meta"); 5 | var ko = require("knockout"); 6 | 7 | var Viewport = Meta.derive(function(){ 8 | return { 9 | tag : "canvas" 10 | } 11 | }, { 12 | type : 'VIEWPORT', 13 | css : "viewport" 14 | }) 15 | 16 | Meta.provideBinding("viewport", Viewport); 17 | 18 | return Viewport; 19 | }) -------------------------------------------------------------------------------- /example/static/modules/viewport/viewport.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DRAG AND DROP THE IMAGE

]]> 5 |
6 |
-------------------------------------------------------------------------------- /example/static/preview/amatorka.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/amatorka.jpg -------------------------------------------------------------------------------- /example/static/preview/bleachbypass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/bleachbypass.jpg -------------------------------------------------------------------------------- /example/static/preview/candlelight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/candlelight.jpg -------------------------------------------------------------------------------- /example/static/preview/canny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/canny.jpg -------------------------------------------------------------------------------- /example/static/preview/crispwarm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/crispwarm.jpg -------------------------------------------------------------------------------- /example/static/preview/crispwinter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/crispwinter.jpg -------------------------------------------------------------------------------- /example/static/preview/dropblues.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/dropblues.jpg -------------------------------------------------------------------------------- /example/static/preview/edgyamber.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/edgyamber.jpg -------------------------------------------------------------------------------- /example/static/preview/fallcolors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/fallcolors.jpg -------------------------------------------------------------------------------- /example/static/preview/filmstock_50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/filmstock_50.jpg -------------------------------------------------------------------------------- /example/static/preview/foggynight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/foggynight.jpg -------------------------------------------------------------------------------- /example/static/preview/futuristicbleak.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/futuristicbleak.jpg -------------------------------------------------------------------------------- /example/static/preview/gaussian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/gaussian.jpg -------------------------------------------------------------------------------- /example/static/preview/grayscale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/grayscale.jpg -------------------------------------------------------------------------------- /example/static/preview/horrorblue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/horrorblue.jpg -------------------------------------------------------------------------------- /example/static/preview/latesunset.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/latesunset.jpg -------------------------------------------------------------------------------- /example/static/preview/missetikate.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/missetikate.jpg -------------------------------------------------------------------------------- /example/static/preview/moonlight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/moonlight.jpg -------------------------------------------------------------------------------- /example/static/preview/nightfromday.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/nightfromday.jpg -------------------------------------------------------------------------------- /example/static/preview/original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/original.jpg -------------------------------------------------------------------------------- /example/static/preview/sepia.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/sepia.jpg -------------------------------------------------------------------------------- /example/static/preview/sketch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/sketch.jpg -------------------------------------------------------------------------------- /example/static/preview/smoothtoon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/smoothtoon.jpg -------------------------------------------------------------------------------- /example/static/preview/sobel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/sobel.jpg -------------------------------------------------------------------------------- /example/static/preview/softelegance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/softelegance.jpg -------------------------------------------------------------------------------- /example/static/preview/softwarming.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/softwarming.jpg -------------------------------------------------------------------------------- /example/static/preview/tealorangepluscontrast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/tealorangepluscontrast.jpg -------------------------------------------------------------------------------- /example/static/preview/tensiongreen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/tensiongreen.jpg -------------------------------------------------------------------------------- /example/static/preview/threshold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/threshold.jpg -------------------------------------------------------------------------------- /example/static/preview/toon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/preview/toon.jpg -------------------------------------------------------------------------------- /example/static/style/imgs/add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/arrow-left-active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/arrow-left-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/arrow-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/arrow-right-active.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/arrow-right-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/arrow-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/black-Linen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/style/imgs/black-Linen.png -------------------------------------------------------------------------------- /example/static/style/imgs/camera.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/cloud.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/local.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/imgs/picture.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/qpf/images/arrow-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/qpf/images/arrow-up.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/style/qpf/images/check_radio_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/style/qpf/images/check_radio_sheet.png -------------------------------------------------------------------------------- /example/static/style/qpf/images/link-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/style/qpf/images/link-active.png -------------------------------------------------------------------------------- /example/static/style/qpf/images/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/style/qpf/images/link.png -------------------------------------------------------------------------------- /example/static/style/qpf/images/slider-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/example/static/style/qpf/images/slider-control.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "emage", 3 | "version" : "0.1.0", 4 | "devDependencies" : { 5 | "grunt" : "*", 6 | "grunt-contrib-requirejs" : "*", 7 | "grunt-contrib-uglify" : "*", 8 | "grunt-contrib-jshint" : "*", 9 | "grunt-contrib-concat" : "*", 10 | "grunt-contrib-clean" : "*", 11 | "grunt-contrib-copy" : "*", 12 | "grunt-contrib-less" : "*", 13 | "grunt-preprocess" : "*" 14 | } 15 | } -------------------------------------------------------------------------------- /src/buildin/blur.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var Blur = function(){ 8 | 9 | FX.call(this); 10 | 11 | this.node = new qtek3d.compositor.Group({ 12 | inputs : { 13 | "texture" : { 14 | node : null, 15 | pin : "color" 16 | } 17 | }, 18 | outputs : { 19 | "color" : {} 20 | } 21 | }); 22 | 23 | var blur_h = new qtek3d.compositor.Node({ 24 | shader : qtek3d.Shader.source("buildin.compositor.gaussian_blur_h"), 25 | groupInputs : { 26 | "texture" : "texture" 27 | }, 28 | outputs : { 29 | "color" : { 30 | parameters : this.imageSize 31 | } 32 | } 33 | }); 34 | 35 | var blur_v = new qtek3d.compositor.Node({ 36 | shader : qtek3d.Shader.source("buildin.compositor.gaussian_blur_v"), 37 | inputs : { 38 | "texture" : { 39 | node : blur_h, 40 | pin : "color" 41 | } 42 | }, 43 | outputs : { 44 | "color" : { 45 | parameters : this.imageSize 46 | } 47 | }, 48 | groupOutputs : { 49 | "color" : "color" 50 | } 51 | }); 52 | 53 | this.node.add(blur_h); 54 | this.node.add(blur_v); 55 | 56 | var blurSize = 1.0; 57 | 58 | // Parameters of gaussian blur 59 | this.parameters = { 60 | blurSize : { 61 | max : 10.0, 62 | min : 0.0, 63 | step : 0.1, 64 | ui : "slider", 65 | get value(){ 66 | return blurSize; 67 | }, 68 | set value(val){ 69 | blurSize = val; 70 | blur_v.setParameter("blurSize", val); 71 | blur_h.setParameter("blurSize", val); 72 | } 73 | } 74 | } 75 | } 76 | 77 | Blur.prototype = new FX(); 78 | Blur.prototype.reset = function(){ 79 | this.parameters.blurSize.value = 2.0; 80 | } 81 | Blur.prototype.constructor = Blur; 82 | 83 | FX.export("buildin.gaussian", Blur); 84 | 85 | return Blur; 86 | }) -------------------------------------------------------------------------------- /src/buildin/boxblur.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | qtek3d.Shader.import(require("text!shaders/box_blur.essl")); 8 | 9 | var BoxBlur = function(){ 10 | 11 | FX.call(this); 12 | 13 | this.node = new qtek3d.compositor.Group({ 14 | inputs : { 15 | "texture" : { 16 | node : null, 17 | pin : "color" 18 | } 19 | }, 20 | outputs : { 21 | "color" : {} 22 | } 23 | }); 24 | 25 | var parameters = { 26 | width : this.imageSize.width, 27 | height : this.imageSize.height, 28 | wrapS : 'REPEAT', 29 | wrapT : 'REPEAT' 30 | } 31 | 32 | var boxblur_h = new qtek3d.compositor.Node({ 33 | name : "boxblur_h", 34 | shader : qtek3d.Shader.source("emage.box_blur_h"), 35 | groupInputs : { 36 | "texture" : "texture" 37 | }, 38 | outputs : { 39 | "color" : { 40 | parameters : parameters 41 | } 42 | } 43 | }); 44 | 45 | var boxblur_v = new qtek3d.compositor.Node({ 46 | name : "boxblur_v", 47 | shader : qtek3d.Shader.source("emage.box_blur_v"), 48 | inputs : { 49 | "texture" : { 50 | node : boxblur_h, 51 | pin : "color" 52 | } 53 | }, 54 | outputs : { 55 | "color" : { 56 | parameters : parameters 57 | } 58 | }, 59 | groupOutputs : { 60 | "color" : "color" 61 | } 62 | }); 63 | 64 | this.node.add(boxblur_h); 65 | this.node.add(boxblur_v); 66 | 67 | var blurSize = 2.0; 68 | 69 | // Parameters of gaussian blur 70 | this.parameters = { 71 | blurSize : { 72 | max : 10.0, 73 | min : 0.0, 74 | step : 0.1, 75 | ui : "slider", 76 | get value(){ 77 | return blurSize; 78 | }, 79 | set value(val){ 80 | blurSize = val; 81 | boxblur_v.setParameter("blurSize", val); 82 | boxblur_h.setParameter("blurSize", val); 83 | } 84 | } 85 | } 86 | 87 | this.reset(); 88 | } 89 | 90 | BoxBlur.prototype = new FX(); 91 | BoxBlur.prototype.reset = function(){ 92 | this.parameters.blurSize.value = 2.0; 93 | } 94 | BoxBlur.prototype.constructor = BoxBlur; 95 | 96 | FX.export("buildin.boxblur", BoxBlur); 97 | 98 | return BoxBlur; 99 | }) -------------------------------------------------------------------------------- /src/buildin/coloradjust.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var ColorAdjust = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : qtek3d.Shader.source("buildin.compositor.coloradjust"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | 25 | var brightness = 0.0, 26 | contrast = 1.0, 27 | exposure = 0.0, 28 | gamma = 1.0, 29 | saturation = 1.0; 30 | 31 | this.parameters = { 32 | brightness : { 33 | max : 1.0, 34 | min : -1.0, 35 | step : 0.1, 36 | ui : "slider", 37 | get value(){ 38 | return brightness; 39 | }, 40 | set value(val){ 41 | brightness = val; 42 | node.setParameter("brightness", val); 43 | } 44 | }, 45 | contrast : { 46 | max : 4.0, 47 | min : 0.0, 48 | step : 0.1, 49 | ui : "slider", 50 | get value(){ 51 | return contrast; 52 | }, 53 | set value(val){ 54 | contrast = val; 55 | node.setParameter("contrast", val); 56 | } 57 | }, 58 | exposure : { 59 | max : 10.0, 60 | min : -10.0, 61 | step : 0.1, 62 | ui : "slider", 63 | get value(){ 64 | return exposure; 65 | }, 66 | set value(val){ 67 | exposure = val; 68 | node.setParameter("exposure", val); 69 | } 70 | }, 71 | gamma : { 72 | max : 3.0, 73 | min : 0.0, 74 | step : 0.1, 75 | ui : "slider", 76 | get value(){ 77 | return gamma; 78 | }, 79 | set value(val){ 80 | gamma = val; 81 | node.setParameter("gamma", val); 82 | } 83 | }, 84 | saturation : { 85 | max : 10.0, 86 | min : 0.0, 87 | step : 0.1, 88 | ui : "slider", 89 | get value(){ 90 | return saturation; 91 | }, 92 | set value(val){ 93 | saturation = val; 94 | node.setParameter("saturation", val); 95 | } 96 | } 97 | } 98 | 99 | this.reset(); 100 | } 101 | 102 | ColorAdjust.prototype = new FX(); 103 | ColorAdjust.prototype.reset = function(){ 104 | this.parameters.brightness.value = 0.0; 105 | this.parameters.exposure.value = 0.0; 106 | this.parameters.contrast.value = 1.0; 107 | this.parameters.saturation.value = 1.0; 108 | this.parameters.gamma.value = 1.0; 109 | } 110 | ColorAdjust.prototype.constructor = ColorAdjust; 111 | 112 | FX.export("buildin.coloradjust", ColorAdjust); 113 | 114 | return ColorAdjust; 115 | }) -------------------------------------------------------------------------------- /src/buildin/colormatrix.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var ColorMatrix = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : require("text!shaders/colormatrix.essl"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | 25 | var colorMatrix = new Float32Array([1, 0, 0, 0, 26 | 0, 1, 0, 0, 27 | 0, 0, 1, 0, 28 | 0, 0, 0, 1]); 29 | var intensity = 1.0; 30 | this.parameters = { 31 | colorMatrix : { 32 | get value(){ 33 | return colorMatrix; 34 | }, 35 | set value(val){ 36 | colorMatrix = val; 37 | node.setParameter("colorMatrix", val); 38 | } 39 | }, 40 | intensity : { 41 | min : 0.0, 42 | max : 1.0, 43 | ui : "slider", 44 | step : 0.01, 45 | get intensity(){ 46 | return intensity; 47 | }, 48 | set intensity(val){ 49 | intensity = val; 50 | node.setParameter("intensity", val); 51 | } 52 | } 53 | } 54 | } 55 | 56 | ColorMatrix.prototype = new FX(); 57 | 58 | ColorMatrix.prototype.constructor = ColorMatrix; 59 | 60 | FX.export("buildin.colormatrix", ColorMatrix); 61 | 62 | return ColorMatrix; 63 | }) -------------------------------------------------------------------------------- /src/buildin/gaussian.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var Gaussian = function(){ 8 | 9 | FX.call(this); 10 | 11 | this.node = new qtek3d.compositor.Group({ 12 | inputs : { 13 | "texture" : { 14 | node : null, 15 | pin : "color" 16 | } 17 | }, 18 | outputs : { 19 | "color" : {} 20 | } 21 | }); 22 | 23 | var parameters = { 24 | width : this.imageSize.width, 25 | height : this.imageSize.height, 26 | wrapS : 'REPEAT', 27 | wrapT : 'REPEAT' 28 | } 29 | 30 | var gaussian_h = new qtek3d.compositor.Node({ 31 | name : "gaussian_h", 32 | shader : qtek3d.Shader.source("buildin.compositor.gaussian_blur_h"), 33 | groupInputs : { 34 | "texture" : "texture" 35 | }, 36 | outputs : { 37 | "color" : { 38 | parameters : parameters 39 | } 40 | } 41 | }); 42 | 43 | var gaussian_v = new qtek3d.compositor.Node({ 44 | name : "gaussian_v", 45 | shader : qtek3d.Shader.source("buildin.compositor.gaussian_blur_v"), 46 | inputs : { 47 | "texture" : { 48 | node : gaussian_h, 49 | pin : "color" 50 | } 51 | }, 52 | outputs : { 53 | "color" : { 54 | parameters : parameters 55 | } 56 | }, 57 | groupOutputs : { 58 | "color" : "color" 59 | } 60 | }); 61 | 62 | this.node.add(gaussian_h); 63 | this.node.add(gaussian_v); 64 | 65 | var blurSize = 2.0; 66 | 67 | // Parameters of gaussian blur 68 | this.parameters = { 69 | blurSize : { 70 | max : 10.0, 71 | min : 0.0, 72 | step : 0.1, 73 | ui : "slider", 74 | get value(){ 75 | return blurSize; 76 | }, 77 | set value(val){ 78 | blurSize = val; 79 | gaussian_v.setParameter("blurSize", val); 80 | gaussian_h.setParameter("blurSize", val); 81 | } 82 | } 83 | } 84 | 85 | this.reset(); 86 | } 87 | 88 | Gaussian.prototype = new FX(); 89 | Gaussian.prototype.reset = function(){ 90 | this.parameters.blurSize.value = 2.0; 91 | } 92 | Gaussian.prototype.constructor = Gaussian; 93 | 94 | FX.export("buildin.gaussian", Gaussian); 95 | 96 | return Gaussian; 97 | }) -------------------------------------------------------------------------------- /src/buildin/grayscale.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var GrayScale = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : qtek3d.Shader.source("buildin.compositor.grayscale"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | } 25 | 26 | GrayScale.prototype = new FX(); 27 | 28 | GrayScale.prototype.constructor = GrayScale; 29 | 30 | FX.export("buildin.grayscale", GrayScale); 31 | 32 | return GrayScale; 33 | }) -------------------------------------------------------------------------------- /src/buildin/hue.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var Hue = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : require("text!shaders/hue.essl"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }); 23 | this.node = node; 24 | 25 | var hue = 0; 26 | this.parameters = { 27 | hue : { 28 | max : 180, 29 | min : -180, 30 | precision : 1.0, 31 | ui : 'slider', 32 | get value(){ 33 | return hue; 34 | }, 35 | set value(val){ 36 | hue = val; 37 | node.setParameter('hueAdjust', val / 180.0 * Math.PI); 38 | } 39 | } 40 | } 41 | 42 | this.reset(); 43 | } 44 | 45 | Hue.prototype = new FX(); 46 | 47 | Hue.prototype.constructor = Hue; 48 | 49 | Hue.prototype.reset = function(){ 50 | this.parameters.hue.value = 0; 51 | } 52 | 53 | FX.export("buildin.hue", Hue); 54 | 55 | return Hue; 56 | }) -------------------------------------------------------------------------------- /src/buildin/lensblur.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | qtek3d.Shader.import(require("text!shaders/hexagonal_blur.essl")); 8 | 9 | var LensBlur = function(){ 10 | 11 | FX.call(this); 12 | 13 | this.node = new qtek3d.compositor.Group({ 14 | inputs : { 15 | "texture" : { 16 | node : null, 17 | pin : "color" 18 | } 19 | }, 20 | outputs : { 21 | "color" : {} 22 | } 23 | }); 24 | 25 | var floatTextureParam = { 26 | width : 1024, 27 | height : 1024, 28 | type : 'FLOAT' 29 | } 30 | 31 | var gammaNode = new qtek3d.compositor.Node({ 32 | shader : require("text!shaders/gamma.essl"), 33 | groupInputs : { 34 | "texture" : "texture" 35 | }, 36 | outputs : { 37 | "color" : { 38 | parameters : floatTextureParam 39 | } 40 | } 41 | }); 42 | 43 | var blurPass1 = new qtek3d.compositor.Node({ 44 | shader : qtek3d.Shader.source("emage.hexagonal_blur_1"), 45 | inputs : { 46 | "texture" : { 47 | node : gammaNode, 48 | pin : "color" 49 | } 50 | }, 51 | outputs : { 52 | "color" : { 53 | parameters : floatTextureParam 54 | } 55 | } 56 | }); 57 | 58 | var blurPass2 = new qtek3d.compositor.Node({ 59 | shader : qtek3d.Shader.source("emage.hexagonal_blur_2"), 60 | inputs : { 61 | "texture" : { 62 | node : gammaNode, 63 | pin : "color" 64 | } 65 | }, 66 | outputs : { 67 | "color" : { 68 | parameters : floatTextureParam 69 | } 70 | } 71 | }); 72 | 73 | var blurPass3 = new qtek3d.compositor.Node({ 74 | shader : qtek3d.Shader.source("emage.hexagonal_blur_3"), 75 | inputs : { 76 | "texture1" : { 77 | node : blurPass1, 78 | pin : "color" 79 | }, 80 | "texture2" : { 81 | node : blurPass2, 82 | pin : "color" 83 | } 84 | }, 85 | outputs : { 86 | "color" : { 87 | parameters : floatTextureParam 88 | } 89 | } 90 | }); 91 | 92 | var gammaInverseNode = new qtek3d.compositor.Node({ 93 | shader : require("text!shaders/gamma.essl"), 94 | inputs : { 95 | "texture" : { 96 | node : blurPass3, 97 | pin : "color" 98 | } 99 | }, 100 | outputs : { 101 | "color" : { 102 | parameters : { 103 | width : 1024, 104 | height : 1024 105 | } 106 | } 107 | }, 108 | groupOutputs : { 109 | "color" : "color" 110 | } 111 | }); 112 | 113 | this.node.add(gammaNode); 114 | this.node.add(blurPass1); 115 | this.node.add(blurPass2); 116 | this.node.add(blurPass3); 117 | this.node.add(gammaInverseNode); 118 | 119 | 120 | var blurSize = 1.0; 121 | var brightness = 6.0; 122 | 123 | this.parameters = { 124 | blurSize : { 125 | max : 10.0, 126 | min : 0.0, 127 | step : 0.1, 128 | ui : "slider", 129 | get value(){ 130 | return blurSize; 131 | }, 132 | set value(val){ 133 | blurSize = val; 134 | blurPass1.setParameter("blurSize", val); 135 | blurPass2.setParameter("blurSize", val); 136 | blurPass3.setParameter("blurSize", val); 137 | } 138 | }, 139 | brightness : { 140 | max : 10.0, 141 | min : 0.0, 142 | step : 0.1, 143 | ui : "slider", 144 | get value(){ 145 | return brightness; 146 | }, 147 | set value(val){ 148 | brightness = val; 149 | gammaNode.setParameter("gamma", val); 150 | gammaInverseNode.setParameter("gamma", 1.0/val); 151 | } 152 | } 153 | } 154 | 155 | this.reset(); 156 | } 157 | 158 | LensBlur.prototype = new FX(); 159 | LensBlur.prototype.reset = function(){ 160 | this.parameters.blurSize.value = 0.4; 161 | this.parameters.brightness.value = 6.0; 162 | } 163 | LensBlur.prototype.constructor = LensBlur; 164 | 165 | FX.export("buildin.lensblur", LensBlur); 166 | 167 | return LensBlur; 168 | }) -------------------------------------------------------------------------------- /src/buildin/lut.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var LUT = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : require("text!shaders/lut.essl"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | 25 | var lookup = new qtek3d.texture.Texture2D({ 26 | minFilter : "NEAREST", 27 | magFilter : 'NEAREST', 28 | generateMipmaps : false, 29 | flipY : false 30 | }); 31 | node.setParameter("lookup", lookup); 32 | 33 | this.parameters = { 34 | lookup : { 35 | get value(){ 36 | return lookup.image 37 | }, 38 | set value(val){ 39 | lookup.image = val; 40 | lookup.dirty(); 41 | } 42 | } 43 | } 44 | } 45 | 46 | LUT.prototype = new FX(); 47 | 48 | LUT.prototype.constructor = LUT; 49 | 50 | FX.export("buildin.lut", LUT); 51 | 52 | return LUT; 53 | }) -------------------------------------------------------------------------------- /src/buildin/sepia.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var ColorMatrix = require("./colormatrix"); 6 | var FX = require("../fx") 7 | 8 | var Sepia = function(){ 9 | 10 | ColorMatrix.call(this); 11 | 12 | this.parameters.colorMatrix.value = new Float32Array([0.3588, 0.7044, 0.1368, 0.0, 13 | 0.2990, 0.5870, 0.1140, 0.0, 14 | 0.2392, 0.4696, 0.0912 ,0.0, 15 | 0, 0, 0, 1.0]); 16 | } 17 | 18 | Sepia.prototype = new ColorMatrix(); 19 | 20 | Sepia.prototype.constructor = Sepia; 21 | 22 | FX.export("buildin.sepia", Sepia); 23 | 24 | return Sepia; 25 | }) -------------------------------------------------------------------------------- /src/buildin/shaders/_imagedirectionalnonmaximumsuppression.essl: -------------------------------------------------------------------------------- 1 | uniform sampler2D texture; 2 | varying vec2 vUv; 3 | 4 | uniform float imageWidth; 5 | uniform float imageHeight; 6 | 7 | uniform float upperThreshold; 8 | uniform float lowerThreshold; 9 | 10 | void main() 11 | { 12 | vec3 currentGradientAndDirection = texture2D(texture, vUv).rgb; 13 | vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(1.0/imageWidth, 1.0/imageHeight); 14 | 15 | float firstSampledGradientMagnitude = texture2D(texture, vUv + gradientDirection).r; 16 | float secondSampledGradientMagnitude = texture2D(texture, vUv - gradientDirection).r; 17 | 18 | float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r); 19 | multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r); 20 | 21 | float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r); 22 | multiplier = multiplier * thresholdCompliance; 23 | 24 | gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0); 25 | } -------------------------------------------------------------------------------- /src/buildin/shaders/_nonmaxiumsuppression.essl: -------------------------------------------------------------------------------- 1 | // this will sample a 1-pixel box around each pixel and determine if the center pixel's red channel is the maximum in that area. If it is, it stays. If not, it is set to 0 for all color components. 2 | varying vec2 vUv; 3 | uniform sampler2D texture; 4 | 5 | uniform float imageWidth; 6 | uniform float imageHeight; 7 | 8 | void main(){ 9 | 10 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 11 | 12 | // top left 13 | float topLeft = texture2D(texture, vUv+vec2(-offset.x, -offset.y)).r; 14 | // top 15 | float top = texture2D(texture, vUv+vec2(0, -offset.y)).r; 16 | // top right 17 | float topRight = texture2D(texture, vUv+vec2(offset.x, -offset.y)).r; 18 | // left 19 | float left = texture2D(texture, vUv+vec2(-offset.x, 0)).r; 20 | // center 21 | float center = texture2D( texture, vUv).r; 22 | // right 23 | float right = texture2D(texture, vUv+vec2(offset.x, 0)).r; 24 | // bottom left 25 | float bottomLeft = texture2D(texture, vUv+vec2(-offset.x, offset.y)).r; 26 | // bottom 27 | float bottom = texture2D(texture, vUv+vec2(0, offset.y)).r; 28 | // bottom right 29 | float bottomRight = texture2D(texture, vUv+offset).r; 30 | 31 | float multiplier = 1.0 - step(center.r, top); 32 | multiplier = multiplier * 1.0 - step(center.r, topLeft); 33 | multiplier = multiplier * 1.0 - step(center.r, left); 34 | multiplier = multiplier * 1.0 - step(center.r, bottomLeft); 35 | 36 | lowp float maxValue = max(center.r, bottom); 37 | maxValue = max(maxValue, bottomRight); 38 | maxValue = max(maxValue, right); 39 | maxValue = max(maxValue, topRight); 40 | 41 | gl_FragColor = vec4((center.rgb * step(maxValue, center.r) * multiplier), 1.0); 42 | } -------------------------------------------------------------------------------- /src/buildin/shaders/_weakpixelinclusion.essl: -------------------------------------------------------------------------------- 1 | // this will sample a 1-pixel box around each pixel and determine if the center pixel's red channel is the maximum in that area. If it is, it stays. If not, it is set to 0 for all color components. 2 | varying vec2 vUv; 3 | uniform sampler2D texture; 4 | 5 | uniform float imageWidth; 6 | uniform float imageHeight; 7 | 8 | void main(){ 9 | 10 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 11 | 12 | // top left 13 | float topLeft = texture2D(texture, vUv+vec2(-offset.x, -offset.y)).r; 14 | // top 15 | float top = texture2D(texture, vUv+vec2(0, -offset.y)).r; 16 | // top right 17 | float topRight = texture2D(texture, vUv+vec2(offset.x, -offset.y)).r; 18 | // left 19 | float left = texture2D(texture, vUv+vec2(-offset.x, 0)).r; 20 | // center 21 | float center = texture2D( texture, vUv).r; 22 | // right 23 | float right = texture2D(texture, vUv+vec2(offset.x, 0)).r; 24 | // bottom left 25 | float bottomLeft = texture2D(texture, vUv+vec2(-offset.x, offset.y)).r; 26 | // bottom 27 | float bottom = texture2D(texture, vUv+vec2(0, offset.y)).r; 28 | // bottom right 29 | float bottomRight = texture2D(texture, vUv+offset).r; 30 | 31 | 32 | float pixelSum = bottomLeft + topRight + topLeft + bottomRight + left + right + bottom + top + center; 33 | float sumTest = step(1.5, pixelSum); 34 | float pixelTest = step(0.01, center); 35 | 36 | gl_FragColor = vec4(vec3(sumTest * pixelTest), 1.0); 37 | } -------------------------------------------------------------------------------- /src/buildin/shaders/alphablend.essl: -------------------------------------------------------------------------------- 1 | varying vec2 vUv; 2 | 3 | uniform sampler2D texture; 4 | uniform sampler2D overlay; 5 | 6 | uniform float percent; 7 | 8 | void main() 9 | { 10 | vec4 tex = texture2D( texture, vUv); 11 | vec4 tex2 = texture2D( overlay, vUv); 12 | 13 | gl_FragColor = vec4(mix(tex.rgb, tex2.rgb, tex2.a*percent), tex.a); 14 | } -------------------------------------------------------------------------------- /src/buildin/shaders/box_blur.essl: -------------------------------------------------------------------------------- 1 | 2 | @export emage.box_blur_v 3 | 4 | uniform sampler2D texture; // the texture with the scene you want to blur 5 | varying vec2 v_Texcoord; 6 | 7 | uniform float blurSize : 3.0; 8 | uniform float imageWidth : 512.0; 9 | 10 | void main(void) 11 | { 12 | vec4 sum = vec4(0.0); 13 | 14 | for(int i = 0; i < 40; i++){ 15 | sum += texture2D(texture, v_Texcoord + vec2(0.0, float(i-20) * blurSize / imageWidth)); 16 | } 17 | gl_FragColor = sum / 40.0; 18 | } 19 | 20 | @end 21 | 22 | @export emage.box_blur_h 23 | 24 | uniform sampler2D texture; 25 | varying vec2 v_Texcoord; 26 | 27 | uniform float blurSize : 3.0; 28 | uniform float imageHeight : 512.0; 29 | 30 | void main(void) 31 | { 32 | vec4 sum = vec4(0.0); 33 | 34 | for(int i = 0; i < 40; i++){ 35 | sum += texture2D(texture, v_Texcoord + vec2(float(i-20) * blurSize / imageHeight, 0.0)); 36 | } 37 | gl_FragColor = sum / 40.0; 38 | } 39 | 40 | @end -------------------------------------------------------------------------------- /src/buildin/shaders/colormatrix.essl: -------------------------------------------------------------------------------- 1 | varying vec2 v_Texcoord; 2 | 3 | uniform sampler2D texture; 4 | 5 | uniform mat4 colorMatrix; 6 | uniform float intensity : 1.0; 7 | 8 | void main() 9 | { 10 | vec4 tex = texture2D(texture, v_Texcoord); 11 | vec4 outputColor = tex * colorMatrix; 12 | 13 | gl_FragColor = intensity * outputColor + ( (1.0-intensity) * tex ); 14 | } -------------------------------------------------------------------------------- /src/buildin/shaders/convolution.essl: -------------------------------------------------------------------------------- 1 | varying vec2 vUv; 2 | uniform sampler2D texture; 3 | uniform mat4 convolutionMatrix; 4 | 5 | uniform float imageWidth; 6 | uniform float imageHeight; 7 | 8 | void main(){ 9 | 10 | vec4 tex = texture2D( texture, vUv); 11 | 12 | vec3 color = vec3(0.0); 13 | 14 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 15 | 16 | // top left 17 | color += texture2D(texture, vUv+vec2(-offset.x, -offset.y)).rgb*convolutionMatrix[0][0]; 18 | // top 19 | color += texture2D(texture, vUv+vec2(0, -offset.y)).rgb*convolutionMatrix[0][1]; 20 | // top right 21 | color += texture2D(texture, vUv+vec2(offset.x, -offset.y)).rgb*convolutionMatrix[0][2]; 22 | // left 23 | color += texture2D(texture, vUv+vec2(-offset.x, 0)).rgb*convolutionMatrix[1][0]; 24 | // center 25 | color += tex.rgb * convolutionMatrix[1][1]; 26 | // right 27 | color += texture2D(texture, vUv+vec2(offset.x, 0)).rgb*convolutionMatrix[1][2]; 28 | // bottom left 29 | color += texture2D(texture, vUv+vec2(-offset.x, offset.y)).rgb*convolutionMatrix[2][0]; 30 | // bottom 31 | color += texture2D(texture, vUv+vec2(0, offset.y)).rgb*convolutionMatrix[2][1]; 32 | // bottom right 33 | color += texture2D(texture, vUv+offset).rgb*convolutionMatrix[2][2]; 34 | 35 | gl_FragColor = vec4(color, tex.a); 36 | } -------------------------------------------------------------------------------- /src/buildin/shaders/gamma.essl: -------------------------------------------------------------------------------- 1 | varying vec2 v_Texcoord; 2 | 3 | uniform sampler2D texture; 4 | uniform float gamma : 1.0; 5 | 6 | void main() 7 | { 8 | vec4 tex = texture2D(texture, v_Texcoord); 9 | 10 | gl_FragColor = vec4(pow(tex.rgb, vec3(gamma)), tex.a); 11 | } -------------------------------------------------------------------------------- /src/buildin/shaders/hexagonal_blur.essl: -------------------------------------------------------------------------------- 1 | @export emage.hexagonal_blur_1 2 | 3 | uniform sampler2D texture; 4 | varying vec2 v_Texcoord; 5 | 6 | uniform float blurSize : 1.0; 7 | 8 | uniform float imageWidth : 512.0; 9 | uniform float imageHeight : 512.0; 10 | 11 | void main(void){ 12 | vec2 offset = vec2(blurSize/imageWidth, blurSize/imageHeight); 13 | 14 | vec4 color = vec4(0.0); 15 | // Top 16 | for(int i = 0; i < 30; i++){ 17 | color += 1.0/30.0 * texture2D(texture, v_Texcoord + vec2(0.0, offset.y * float(i)) ); 18 | } 19 | gl_FragColor = color; 20 | } 21 | 22 | @end 23 | 24 | @export emage.hexagonal_blur_2 25 | 26 | uniform sampler2D texture; 27 | varying vec2 v_Texcoord; 28 | 29 | uniform float blurSize : 1.0; 30 | 31 | uniform float imageWidth : 512.0; 32 | uniform float imageHeight : 512.0; 33 | 34 | void main(void){ 35 | vec2 offset = vec2(blurSize/imageWidth, blurSize/imageHeight); 36 | 37 | vec4 color = vec4(0.0); 38 | // Down left 39 | for(int i = 0; i < 30; i++){ 40 | color += 1.0/30.0 * texture2D(texture, v_Texcoord - vec2(offset.x * float(i), offset.y * float(i)) ); 41 | } 42 | gl_FragColor = color; 43 | } 44 | @end 45 | 46 | @export emage.hexagonal_blur_3 47 | 48 | uniform sampler2D texture1; 49 | uniform sampler2D texture2; 50 | 51 | varying vec2 v_Texcoord; 52 | 53 | uniform float blurSize : 1.0; 54 | 55 | uniform float imageWidth : 1.0; 56 | uniform float imageHeight : 1.0; 57 | 58 | void main(void){ 59 | vec2 offset = vec2(blurSize/imageWidth, blurSize/imageHeight); 60 | 61 | vec4 color1 = vec4(0.0); 62 | // Down left 63 | for(int i = 0; i < 30; i++){ 64 | color1 += 1.0/30.0 * texture2D(texture1, v_Texcoord - vec2(offset.x * float(i), offset.y * float(i)) ); 65 | } 66 | vec4 color2 = vec4(0.0); 67 | // Down right 68 | for(int i = 0; i < 30; i++){ 69 | color2 += 1.0/30.0 * texture2D(texture1, v_Texcoord + vec2(offset.x * float(i), -offset.y * float(i)) ); 70 | } 71 | 72 | vec4 color3 = vec4(0.0); 73 | // Down right 74 | for(int i = 0; i < 30; i++){ 75 | color3 += 1.0/30.0 * texture2D(texture2, v_Texcoord + vec2(offset.x * float(i), -offset.y * float(i)) ); 76 | } 77 | 78 | gl_FragColor = (color1 + color2 + color3) / 3.0; 79 | } 80 | 81 | @end -------------------------------------------------------------------------------- /src/buildin/shaders/histogram.essl: -------------------------------------------------------------------------------- 1 | //Red channel 2 | @export emage.histogram_r.vertex 3 | 4 | attribute vec4 position; 5 | 6 | varying lowp vec3 colorFactor; 7 | 8 | void main() 9 | { 10 | colorFactor = vec3(1.0, 0.0, 0.0); 11 | gl_Position = vec4(-1.0 + position.x * 0.0078125, 0.0, 0.0, 1.0); 12 | gl_PointSize = 1.0; 13 | } 14 | 15 | @end 16 | 17 | //Grenn channel 18 | @export emage.histogram_g.vertex 19 | 20 | attribute vec4 position : POSITION; 21 | 22 | varying lowp vec3 colorFactor; 23 | 24 | void main() 25 | { 26 | colorFactor = vec3(0.0, 1.0, 0.0); 27 | gl_Position = vec4(-1.0 + position.y * 0.0078125, 0.0, 0.0, 1.0); 28 | gl_PointSize = 1.0; 29 | } 30 | 31 | @end 32 | 33 | //Blue channel 34 | @export emage.histogram_b.vertex 35 | 36 | attribute vec4 position : POSITION; 37 | 38 | varying lowp vec3 colorFactor; 39 | 40 | void main() 41 | { 42 | colorFactor = vec3(0.0, 0.0, 1.0); 43 | gl_Position = vec4(-1.0 + position.z * 0.0078125, 0.0, 0.0, 1.0); 44 | gl_PointSize = 1.0; 45 | } 46 | 47 | @end 48 | 49 | //Luminance channel 50 | @export emage.histogram_l.vertex 51 | 52 | attribute vec4 position : POSITION; 53 | 54 | varying lowp vec3 colorFactor; 55 | const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); 56 | 57 | void main() 58 | { 59 | colorFactor = vec3(1.0, 1.0, 1.0); 60 | gl_Position = vec4(-1.0 + dot(position.xyz, W) * 0.0078125, 0.0, 0.0, 1.0); 61 | gl_PointSize = 1.0; 62 | } 63 | 64 | @end 65 | 66 | @export emage.histogram.fragment 67 | 68 | const lowp float scalingFactor = 1.0 / 256.0; 69 | 70 | varying lowp vec3 colorFactor; 71 | 72 | void main() 73 | { 74 | gl_FragColor = vec4(colorFactor * scalingFactor, 1.0); 75 | } 76 | 77 | @end 78 | 79 | -------------------------------------------------------------------------------- /src/buildin/shaders/hue.essl: -------------------------------------------------------------------------------- 1 | varying vec2 v_Texcoord; 2 | 3 | uniform sampler2D texture; 4 | uniform float hueAdjust; 5 | 6 | const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0); 7 | const vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0); 8 | const vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0); 9 | 10 | const vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0); 11 | const vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0); 12 | const vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0); 13 | 14 | 15 | 16 | void main () 17 | { 18 | // Sample the input pixel 19 | vec4 color = texture2D(texture, v_Texcoord); 20 | 21 | // Convert to YIQ 22 | float YPrime = dot (color, kRGBToYPrime); 23 | float I = dot (color, kRGBToI); 24 | float Q = dot (color, kRGBToQ); 25 | 26 | // Calculate the hue and chroma 27 | float hue = atan (Q, I); 28 | float chroma = sqrt (I * I + Q * Q); 29 | 30 | // Make the user's adjustments 31 | hue += (-hueAdjust); //why negative rotation? 32 | 33 | // Convert back to YIQ 34 | Q = chroma * sin (hue); 35 | I = chroma * cos (hue); 36 | 37 | // Convert back to RGB 38 | vec4 yIQ = vec4 (YPrime, I, Q, 0.0); 39 | color.r = dot (yIQ, kYIQToR); 40 | color.g = dot (yIQ, kYIQToG); 41 | color.b = dot (yIQ, kYIQToB); 42 | 43 | // Save the result 44 | gl_FragColor = color; 45 | } -------------------------------------------------------------------------------- /src/buildin/shaders/level.essl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pissang/emage/60c31f9b952d69dd9ef6cd33c8fe16c1e6fba44e/src/buildin/shaders/level.essl -------------------------------------------------------------------------------- /src/buildin/shaders/lut.essl: -------------------------------------------------------------------------------- 1 | varying vec2 v_Texcoord; 2 | 3 | uniform sampler2D texture; 4 | uniform sampler2D lookup; 5 | 6 | void main() 7 | { 8 | vec4 tex = texture2D(texture, v_Texcoord); 9 | 10 | float blueColor = tex.b * 63.0; 11 | 12 | vec2 quad1; 13 | quad1.y = floor(floor(blueColor) / 8.0); 14 | quad1.x = floor(blueColor) - (quad1.y * 8.0); 15 | 16 | vec2 quad2; 17 | quad2.y = floor(ceil(blueColor) / 8.0); 18 | quad2.x = ceil(blueColor) - (quad2.y * 8.0); 19 | 20 | vec2 texPos1; 21 | texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r); 22 | texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g); 23 | 24 | vec2 texPos2; 25 | texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.r); 26 | texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * tex.g); 27 | 28 | vec4 newColor1 = texture2D(lookup, texPos1); 29 | vec4 newColor2 = texture2D(lookup, texPos2); 30 | 31 | vec4 newColor = mix(newColor1, newColor2, fract(blueColor)); 32 | gl_FragColor = vec4(newColor.rgb, tex.w); 33 | } -------------------------------------------------------------------------------- /src/buildin/shaders/sketch.essl: -------------------------------------------------------------------------------- 1 | varying vec2 v_Texcoord; 2 | uniform sampler2D texture; 3 | 4 | uniform float imageWidth : 512; 5 | uniform float imageHeight : 512; 6 | 7 | const vec3 w = vec3(0.2125, 0.7154, 0.0721); 8 | float luminance(vec4 color){ 9 | return dot(color.rgb, w); 10 | } 11 | 12 | void main(){ 13 | 14 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 15 | 16 | // top left 17 | float topLeft = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, -offset.y)) ); 18 | // top 19 | float top = luminance( texture2D(texture, v_Texcoord+vec2(0, -offset.y)) ); 20 | // top right 21 | float topRight = luminance( texture2D(texture, v_Texcoord+vec2(offset.x, -offset.y)) ); 22 | // left 23 | float left = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, 0)) ); 24 | // center 25 | float center = luminance( texture2D( texture, v_Texcoord) ); 26 | // right 27 | float right = luminance( texture2D(texture, v_Texcoord+vec2(offset.x, 0)) ); 28 | // bottom left 29 | float bottomLeft = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, offset.y)) ); 30 | // bottom 31 | float bottom = luminance( texture2D(texture, v_Texcoord+vec2(0, offset.y)) ); 32 | // bottom right 33 | float bottomRight = luminance( texture2D(texture, v_Texcoord+offset) ); 34 | 35 | float h = -topLeft-2.0*top-topRight+bottomLeft+2.0*bottom+bottomRight; 36 | float v = -bottomLeft-2.0*left-topLeft+bottomRight+2.0*right+topRight; 37 | 38 | float mag = 1.0 - length(vec2(h, v)); 39 | 40 | gl_FragColor = vec4(vec3(mag), 1.0); 41 | } -------------------------------------------------------------------------------- /src/buildin/shaders/sobel.essl: -------------------------------------------------------------------------------- 1 | // Sobel edge detection 2 | // http://en.wikipedia.org/wiki/Sobel_operator 3 | // 4 | varying vec2 v_Texcoord; 5 | uniform sampler2D texture; 6 | 7 | uniform float imageWidth : 512; 8 | uniform float imageHeight : 512; 9 | 10 | const vec3 w = vec3(0.2125, 0.7154, 0.0721); 11 | float luminance(vec4 color){ 12 | return dot(color.rgb, w); 13 | } 14 | 15 | void main(){ 16 | 17 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 18 | 19 | // top left 20 | float topLeft = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, -offset.y)) ); 21 | // top 22 | float top = luminance( texture2D(texture, v_Texcoord+vec2(0, -offset.y)) ); 23 | // top right 24 | float topRight = luminance( texture2D(texture, v_Texcoord+vec2(offset.x, -offset.y)) ); 25 | // left 26 | float left = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, 0)) ); 27 | // center 28 | float center = luminance( texture2D( texture, v_Texcoord) ); 29 | // right 30 | float right = luminance( texture2D(texture, v_Texcoord+vec2(offset.x, 0)) ); 31 | // bottom left 32 | float bottomLeft = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, offset.y)) ); 33 | // bottom 34 | float bottom = luminance( texture2D(texture, v_Texcoord+vec2(0, offset.y)) ); 35 | // bottom right 36 | float bottomRight = luminance( texture2D(texture, v_Texcoord+offset) ); 37 | 38 | float h = -topLeft-2.0*top-topRight+bottomLeft+2.0*bottom+bottomRight; 39 | float v = -bottomLeft-2.0*left-topLeft+bottomRight+2.0*right+topRight; 40 | 41 | float mag = length(vec2(h,v)); 42 | gl_FragColor = vec4(vec3(mag), 1.0); 43 | } -------------------------------------------------------------------------------- /src/buildin/shaders/thresholdedge.essl: -------------------------------------------------------------------------------- 1 | // Sobel edge detection 2 | // http://en.wikipedia.org/wiki/Sobel_operator 3 | // 4 | varying vec2 vUv; 5 | uniform sampler2D texture; 6 | 7 | uniform float imageWidth; 8 | uniform float imageHeight; 9 | 10 | uniform float threshold; 11 | 12 | void main(){ 13 | 14 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 15 | 16 | // top left 17 | float topLeft = texture2D(texture, vUv+vec2(-offset.x, -offset.y)).r; 18 | // top 19 | float top = texture2D(texture, vUv+vec2(0, -offset.y)).r; 20 | // top right 21 | float topRight = texture2D(texture, vUv+vec2(offset.x, -offset.y)).r; 22 | // left 23 | float left = texture2D(texture, vUv+vec2(-offset.x, 0)).r; 24 | // center 25 | float center = texture2D( texture, vUv).r; 26 | // right 27 | float right = texture2D(texture, vUv+vec2(offset.x, 0)).r; 28 | // bottom left 29 | float bottomLeft = texture2D(texture, vUv+vec2(-offset.x, offset.y)).r; 30 | // bottom 31 | float bottom = texture2D(texture, vUv+vec2(0, offset.y)).r; 32 | // bottom right 33 | float bottomRight = texture2D(texture, vUv+offset).r; 34 | 35 | float h = -topLeft-2.0*top-topRight+bottomLeft+2.0*bottom+bottomRight; 36 | float v = -bottomLeft-2.0*left-topLeft+bottomRight+2.0*right+topRight; 37 | 38 | float mag = length(vec2(h,v)); 39 | mag = step(threshold, mag); 40 | 41 | gl_FragColor = vec4(vec3(mag), 1.0); 42 | } -------------------------------------------------------------------------------- /src/buildin/shaders/toon.essl: -------------------------------------------------------------------------------- 1 | varying vec2 v_Texcoord; 2 | uniform sampler2D texture; 3 | 4 | uniform float imageWidth; 5 | uniform float imageHeight; 6 | 7 | uniform float threshold : 0.2; 8 | uniform float quantizationLevels : 10; 9 | 10 | const vec3 w = vec3(0.2125, 0.7154, 0.0721); 11 | float luminance(vec4 color){ 12 | return dot(color.rgb, w); 13 | } 14 | 15 | void main(){ 16 | 17 | vec2 offset = vec2(1.0/imageWidth, 1.0/imageHeight); 18 | vec4 tex = texture2D(texture, v_Texcoord); 19 | // top left 20 | float topLeft = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, -offset.y)) ); 21 | // top 22 | float top = luminance( texture2D(texture, v_Texcoord+vec2(0, -offset.y)) ); 23 | // top right 24 | float topRight = luminance( texture2D(texture, v_Texcoord+vec2(offset.x, -offset.y)) ); 25 | // left 26 | float left = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, 0)) ); 27 | // center 28 | float center = luminance( texture2D( texture, v_Texcoord) ); 29 | // right 30 | float right = luminance( texture2D(texture, v_Texcoord+vec2(offset.x, 0)) ); 31 | // bottom left 32 | float bottomLeft = luminance( texture2D(texture, v_Texcoord+vec2(-offset.x, offset.y)) ); 33 | // bottom 34 | float bottom = luminance( texture2D(texture, v_Texcoord+vec2(0, offset.y)) ); 35 | // bottom right 36 | float bottomRight = luminance( texture2D(texture, v_Texcoord+offset) ); 37 | 38 | float h = -topLeft-2.0*top-topRight+bottomLeft+2.0*bottom+bottomRight; 39 | float v = -bottomLeft-2.0*left-topLeft+bottomRight+2.0*right+topRight; 40 | 41 | float mag = length(vec2(h, v)); 42 | 43 | vec3 posterizedImageColor = floor((tex.rgb * quantizationLevels) + 0.5) / quantizationLevels; 44 | float thresholdTest = 1.0 - step(threshold, mag); 45 | 46 | gl_FragColor = vec4(posterizedImageColor * thresholdTest, tex.a); 47 | } -------------------------------------------------------------------------------- /src/buildin/sketch.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var Sketch = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : require("text!shaders/sketch.essl"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | } 25 | 26 | Sketch.prototype = new FX(); 27 | 28 | Sketch.prototype.constructor = Sketch; 29 | 30 | FX.export("buildin.sketch", Sketch); 31 | 32 | return Sketch; 33 | }) -------------------------------------------------------------------------------- /src/buildin/sobel.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var Sobel = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : require("text!shaders/sobel.essl"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | } 25 | 26 | Sobel.prototype = new FX(); 27 | 28 | Sobel.prototype.constructor = Sobel; 29 | 30 | FX.export("buildin.sobel", Sobel); 31 | 32 | return Sobel; 33 | }) -------------------------------------------------------------------------------- /src/buildin/toon.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek["3d"]; 5 | var FX = require("../fx"); 6 | 7 | var Toon = function(){ 8 | 9 | FX.call(this); 10 | 11 | var node = new qtek3d.compositor.Node({ 12 | shader : require("text!shaders/toon.essl"), 13 | inputs : { 14 | "texture" : { 15 | node : null, 16 | pin : "color" 17 | } 18 | }, 19 | outputs : { 20 | "color" : {} 21 | } 22 | }) 23 | this.node = node; 24 | 25 | var threshold = 0.2, 26 | quantizationLevels = 10; 27 | this.parameters = { 28 | threshold : { 29 | ui : "slider", 30 | min : 0, 31 | max : 2, 32 | get value(){ 33 | return threshold; 34 | }, 35 | set value(val){ 36 | threshold = val; 37 | node.setParameter("threshold", val); 38 | } 39 | }, 40 | quantizationLevels : { 41 | ui : "spinner", 42 | min : 2, 43 | precision : 0, 44 | get value(){ 45 | return quantizationLevels; 46 | }, 47 | set value(val){ 48 | quantizationLevels = val; 49 | node.setParameter("quantizationLevels", val); 50 | } 51 | } 52 | } 53 | } 54 | 55 | Toon.prototype = new FX(); 56 | 57 | Toon.prototype.constructor = Toon; 58 | 59 | Toon.prototype.reset = function(){ 60 | this.parameters.threshold.value = 0.2; 61 | this.parameters.quantizationLevels.value = 10; 62 | } 63 | 64 | FX.export("buildin.toon", Toon); 65 | 66 | return Toon; 67 | }) -------------------------------------------------------------------------------- /src/emage.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var emage = { 4 | FX : require("./fx"), 5 | Layer : require("./layer"), 6 | Processor : require("./processor"), 7 | Histogram : require("./histogram"), 8 | 9 | qtek : require("qtek") 10 | } 11 | 12 | return emage; 13 | }) -------------------------------------------------------------------------------- /src/fx.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for all fx 3 | * Each fx input texture channel and output color channel 4 | */ 5 | define(function(require){ 6 | 7 | var qtek = require("qtek"); 8 | var qtek3d = qtek["3d"]; 9 | 10 | var FX = function(){ 11 | this.node = null; 12 | this.input = null; 13 | 14 | this.parameters = {}; 15 | 16 | this.imageSize = { 17 | width : 512, 18 | height : 512 19 | } 20 | 21 | Object.defineProperty(this, "input", { 22 | set : function(value){ 23 | if(this.node){ 24 | this.node.inputs.texture.node = value; 25 | } 26 | }, 27 | get : function(){ 28 | return this.node.inputs.texture.node; 29 | } 30 | }); 31 | } 32 | 33 | FX.prototype.reset = function(){}; 34 | FX.prototype.dispose = function(){ 35 | 36 | }; 37 | FX.prototype.setImageSize = function(width, height){ 38 | if( ! this.node){ 39 | return; 40 | } 41 | if(this.node.instanceof(qtek3d.compositor.Group)){ 42 | for(var i = 0; i < this.node.nodes.length; i++){ 43 | var node = this.node.nodes[i]; 44 | node.setParameters({ 45 | imageWidth : width, 46 | imageHeight : height 47 | }) 48 | if(node.outputs){ 49 | for(var name in node.outputs){ 50 | var info = node.outputs[name]; 51 | if( ! info.parameters){ 52 | info.parameters = { 53 | width : width, 54 | height : height 55 | } 56 | }else if( ! info.parameters.width){ 57 | info.parameters.width = width; 58 | info.parameters.height = height; 59 | } 60 | } 61 | } 62 | } 63 | }else{ 64 | this.node.setParameters({ 65 | imageWidth : width, 66 | imageHeight : height 67 | }) 68 | var node = this.node; 69 | if(node.outputs){ 70 | for(var name in node.outputs){ 71 | var info = node.outputs[name]; 72 | if( ! info.parameters){ 73 | info.parameters = { 74 | width : width, 75 | height : height 76 | } 77 | }else if( ! info.parameters.width){ 78 | info.parameters.width = width; 79 | info.parameters.height = height; 80 | } 81 | } 82 | } 83 | } 84 | } 85 | 86 | var fxFactory = {}; 87 | FX.export = function(name, constructor){ 88 | fxFactory[name] = constructor; 89 | } 90 | FX.create = function(name){ 91 | if(fxFactory[name]){ 92 | var fx = new fxFactory[name](); 93 | }else{ 94 | console.error("FX " + name + " not exist"); 95 | return; 96 | } 97 | return fx; 98 | } 99 | 100 | return FX; 101 | }) -------------------------------------------------------------------------------- /src/layer.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var FX = require("./fx"); 5 | 6 | var Layer = function(fxName){ 7 | 8 | this.fx = null; 9 | this.enabled = true; 10 | 11 | this.prevSibling = null; 12 | this.nextSibling = null; 13 | 14 | this._fxCaches = {}; 15 | 16 | if(fxName){ 17 | this.use(fxName); 18 | } 19 | } 20 | 21 | Layer.prototype.use = function(fxName){ 22 | var fx = this._fxCaches[fxName]; 23 | if(!fx){ 24 | fx = FX.create(fxName); 25 | }else{ 26 | fx.reset(); 27 | } 28 | if(fx){ 29 | fx.input = this.prevSibling; 30 | this._fxCaches[fxName] = fx; 31 | this.fx = fx; 32 | return fx; 33 | } 34 | } 35 | 36 | Layer.prototype.set = function(name, value){ 37 | if( ! name){ 38 | return; 39 | } 40 | if(typeof(name) === "object"){ 41 | var obj = name; 42 | for(var name in obj){ 43 | this.set(name, obj[name]); 44 | } 45 | return; 46 | } 47 | if( this.fx && 48 | this.fx.parameters[name]){ 49 | this.fx.parameters[name].value = value; 50 | } 51 | } 52 | 53 | // Buildin fxs 54 | // Most from GPUImage 55 | // https://github.com/BradLarson/GPUImage 56 | require("./buildin/gaussian"); 57 | require("./buildin/lensblur"); 58 | require("./buildin/boxblur"); 59 | require("./buildin/coloradjust"); 60 | require("./buildin/hue"); 61 | require("./buildin/colormatrix"); 62 | require("./buildin/sepia"); 63 | require("./buildin/lut"); 64 | require("./buildin/sobel"); 65 | require("./buildin/sketch"); 66 | require("./buildin/toon"); 67 | require("./buildin/grayscale"); 68 | 69 | return Layer; 70 | }) -------------------------------------------------------------------------------- /src/processor.js: -------------------------------------------------------------------------------- 1 | define(function(require){ 2 | 3 | var qtek = require("qtek"); 4 | var qtek3d = qtek['3d']; 5 | var Layer = require("./layer"); 6 | var FX = require("./fx"); 7 | 8 | var Processor = function(canvas, image){ 9 | 10 | this.canvas = canvas || document.createElement("canvas"); 11 | 12 | this.renderer = new qtek3d.Renderer({ 13 | canvas : this.canvas, 14 | devicePixelRatio : 1.0 15 | }); 16 | this.scale = 1.0; 17 | this.compositor = new qtek3d.Compositor(); 18 | 19 | this.layers = []; 20 | 21 | this._inputNode = new qtek3d.compositor.TextureNode({ 22 | texture : new qtek3d.texture.Texture2D({ 23 | image : null 24 | }), 25 | outputs : { 26 | "color" : { 27 | parameters : { 28 | width : 1024, 29 | height : 1024, 30 | wrapS : 'REPEAT', 31 | wrapT : 'REPEAT' 32 | } 33 | } 34 | } 35 | }); 36 | this._outputNode = new qtek3d.compositor.Node({ 37 | shader : qtek3d.Shader.source("buildin.compositor.output"), 38 | inputs : { 39 | "texture" : { 40 | node : null, 41 | pin : "color" 42 | } 43 | } 44 | }) 45 | 46 | this._imageChanged = true; 47 | Object.defineProperty(this, "image", { 48 | set : function(value){ 49 | this._inputNode.texture.image = value; 50 | this._inputNode.texture.dirty(); 51 | this._imageChanged = true; 52 | }, 53 | get : function(value){ 54 | return this._inputNode.texture.image 55 | } 56 | }); 57 | 58 | this.image = image || null; 59 | } 60 | 61 | Processor.prototype.add = function(layer){ 62 | this.layers.push(layer); 63 | } 64 | Processor.prototype.remove = function(layer){ 65 | var idx = this.layers.indexOf(layer); 66 | this.layers.splice(idx, 1); 67 | } 68 | Processor.prototype.update = function(){ 69 | 70 | var layers = []; 71 | // Filter the enabled layer 72 | for(var i = 0; i < this.layers.length; i++){ 73 | var layer = this.layers[i]; 74 | if(layer.enabled && layer.fx){ 75 | layers.push(this.layers[i]); 76 | } 77 | } 78 | // Update linked list 79 | for(var i = 0; i < layers.length; i++){ 80 | var layer = layers[i], 81 | layerPrev = layers[i-1] || null, 82 | layerNext = layers[i+1] || null; 83 | layer.prevSibling = layerPrev; 84 | layer.nextSibling = layerNext; 85 | if(layerPrev){ 86 | layer.fx.input = layerPrev.fx.node; 87 | } 88 | } 89 | if(layers.length){ 90 | this._outputNode.inputs['texture'].node = layers[layers.length-1].fx.node; 91 | layers[0].fx.input = this._inputNode; 92 | }else{ 93 | this._outputNode.inputs.texture.node = this._inputNode; 94 | } 95 | 96 | var width = this.image.width * this.scale; 97 | var height = this.image.height * this.scale; 98 | 99 | if(this._imageChanged){ 100 | this.renderer.resize( width, height ); 101 | } 102 | 103 | this.compositor.nodes = []; 104 | // Update graph 105 | for(var i = 0; i < layers.length; i++){ 106 | this.compositor.add(layers[i].fx.node); 107 | if(this._imageChanged){ 108 | layers[i].fx.setImageSize(width, height); 109 | } 110 | } 111 | this._inputNode.outputs.color.parameters = { 112 | width : width, 113 | height : height 114 | } 115 | this.compositor.add(this._inputNode); 116 | this.compositor.add(this._outputNode); 117 | 118 | this.compositor.render(this.renderer); 119 | } 120 | 121 | return Processor; 122 | }) -------------------------------------------------------------------------------- /tests/histogram.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 37 | 38 | -------------------------------------------------------------------------------- /tests/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | 2 | requirejs.config({ 3 | 'baseUrl' : "./", 4 | 'paths' : { 5 | "qtek" : "../thirdparty/qtek.image", 6 | "text" : "../src/text", 7 | "shaders" : "../src/buildin/shaders" 8 | } 9 | }) 10 | 11 | require(["../src/processor", 12 | "../src/layer"], function(Processor, Layer){ 13 | 14 | var img = new Image(); 15 | var processor = new Processor(); 16 | processor.image = img; 17 | document.body.appendChild(processor.canvas); 18 | processor.canvas.style.width = 1000 + "px"; 19 | var layer = new Layer("buildin.boxblur"); 20 | processor.add(layer); 21 | // layer2.set("gamma", 2.0) 22 | 23 | img.onload = function(){ 24 | processor.update(); 25 | } 26 | img.src = "../example/file_upload/1.jpg"; 27 | }) -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd ../qpf/build 3 | node r.js -o config.js 4 | cp ../dist/qpf.js ../../emage/example/static/lib/qpf.js 5 | 6 | cp ../src/components/tyle/base.less ../../emage/example/static/style/qpf/base.less 7 | # cp -r ../src/components/less/images ../../emage/example/static/style/qpf/images 8 | 9 | #cd ../../qtek 10 | #grunt image 11 | #cp dist/qtek.image.js ../qtek-image/thirdpart/qtek.image.js --------------------------------------------------------------------------------