evanw / glfx.js Goto Github PK
View Code? Open in Web Editor NEWAn image effects library for JavaScript using WebGL
Home Page: https://evanw.github.io/glfx.js/
License: MIT License
An image effects library for JavaScript using WebGL
Home Page: https://evanw.github.io/glfx.js/
License: MIT License
I found this implementation of a barrel distortion (also known as lens distortion) filter using WebGL here:
https://github.com/bluemir/fisheye-correction-webgl
I forked it and got a demo running in Github Pages: https://jywarren.github.io/fisheye-correction-webgl/
It's pretty simple and includes shaders: https://github.com/jywarren/fisheye-correction-webgl/tree/master/shaders
I'm curious -- I'm not a WebGL programmer, but it'd be really great if this could be integrated into a more standardized suite of filters such as glfx.js
. Is anyone able to help adapt it?
Demo screenshot below:
Hello,
Why does it not allow to stack more than just two certain filters? This allows only brightness and contrast for example. Or hue and saturation. But not brightness and hue.
Or am I mistaken? Is there a way to apply unlimited filters to an image?
On some computers (found on Intel HD 3000 graphic), tiltSift effect adds darker 1px border at top and right.
Hi,
when using glfx in the latest stable chrome version it seems to crash the tab.
I'm using Windows 7. It works fine in the Chrome beta (v.18) though. But I still feel somewhat uneasy about this.
How to crash it:
I wrote a page to test this scenario: http://dl.dropbox.com/u/38743/glfxTest/glfx.html
To further investigate this issue, I decided to recreate the functionality of glfx for this case (just drawing a rectangle with the ink shader). To my surprise it doesn't crash and stays stable even when applying the filter on the 2d canvas in multiple passes(that usually caused an instant crash with glfx).
http://dl.dropbox.com/u/38743/glfxTest/rebuild.html
As mentioned before this problem is gone with Chrome 18 ... but still I wonder what might be the cause of this.
I guess I'll have to wait it out (disabling glfx features for my web app) until 18 is stable.
greets
Trying demo.js modified on my system with my own image files causes a javascript error:
"Cannot read property 'parentNode' of undefined"
This doesn't happen if I avoid placeholder.parentNode.removeChild(placeholder).
But then I am left with 2 canvases on screen.
i have worked with tui image editor and there are some features that tui image editor does not have but glfx.js has how do i combine both of them?
`
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/magic-wand.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/magic-wand.js"></script>
<!-- <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> -->
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<style>
@import url(http://fonts.googleapis.com/css?family=Noto+Sans);
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
width: 400px !important;
height: 350px !important;
overflow: auto !important;
}
.content {
position: relative !important;
}
.canvas {
position: absolute;
}
.canvas:hover {
cursor: default;
}
.picture {
position: absolute;
}
.button {
padding: 4px;
margin: 4px;
border: 1px solid black;
float: left;
}
.button:hover {
background-color: blue;
color: white;
cursor: pointer;
}
#threshold {
width: 95px;
float: left;
}
#file-upload {
display: none;
}
.add-mode {
cursor: copy !important;
}
#imgcanvas {
position: relative;
}
#imgcanvas .wrapper {
position: absolute;
top: 86.5px;
/* left: 50%; /
/ top: calc(333px - var(--img-height) / 2) ; /
left: calc(874px - var(--img-width) / 2) ;
transform: translateX(-50%);
z-index: 9999;
/ width: 400px; /
/ height: 350px; */
overflow: auto;
}
#imgcanvas .content {
position: relative;
}
</style>
<script>
let hue_num = 1;
var imageEditor = new tui.ImageEditor('#tui-image-editor-container', {
includeUI: {
loadImage: {
path: 'image2.png',
name: 'SampleImage',
},
// theme: blackTheme,
initMenu: 'filter',
menuBarPosition: 'bottom',
},
cssMaxWidth: 700,
cssMaxHeight: 500,
usageStatistics: false,
});
window.onresize = function () {
imageEditor.ui.resizeEditor();
};
setTimeout(() => {
try {
var canvas_glfx = fx.canvas();
// alert(canvas_glfx)
alert("ink funciton part 3")
} catch (e) {
alert(e);
return;
}
// var image_glfx = document.getElementById('image');
var image_glfx = imageEditor._graphics.getCanvas();
var texture_glfx = canvas_glfx.texture(image_glfx);
canvas_glfx.draw(texture_glfx).ink(0.95).update();
image_glfx.parentNode.insertBefore(canvas_glfx, image_glfx);
image_glfx.parentNode.removeChild(image_glfx);
}, 2000);
Hello,
the interpolation function to generate the 255 points of the rgb channels is wrong:
glfx.js line 806 is
function splineInterpolate(points) { var interpolator = new SplineInterpolator(points); var array = []; for (var i = 0; i < 256; i++) { array.push(clamp(0, Math.floor(interpolator.interpolate(i / 255) * 256), 255)); } return array; }
the line
array.push(clamp(0, Math.floor(interpolator.interpolate(i / 255) * 256), 255));
make no sense, probably it should be:
array.push(clamp(0, Math.floor((interpolator.interpolate(i) / 255) * 256), 255));
RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
when I use phython3.7 to run build.py, then use the glfx.js just built with demo, it comes out this warning and the canvas can't render in chrome, but if I use "http://evanw.github.com/glfx.js/glfx.js", is works.
does anyone came up with the same problem?
I assume maybe I should use phython 2.x, does is matters?
React-native and Expo has WebGL support, but seems like this library relies on window.document
Hi evanw,
I'm working on a shader building enviroment you can see the very very early release here
http://shady-oio.dotcloud.com/
I am using glfx as it really nicely hides all the webgl stuff i;m not too familiar with.
I wanted to know if there is a clean way to load shaders to the canvas element
currently i iam using this code
this.canvas[name] = fx.wrap(function(time) {
code = code.replace(/\n/g,'');
codeShader = new fx.Shader(null, code);
fx.simpleShader.call(this, codeShader, {
time: time,
resolution: [this.width, this.height]
});
return this;
})
which had required me to export the wrap,Shader and simpleShader functions that were hidden.
Is there a better way to do this?
in addition i add a globle time uniform, which was great if it was built in the lib
great stuff (by the way)
(Credit page is in the making)
I'm developing a complex app, and I really appreciate how much of the busywork this API removes; it's difficult to find good tutorials on 2d webgl!
But, I want to write a filter that is deeply connected to my own code, and there seems no way to import a new filter from external code: you seem to require that it be built in via the python build script.
Is there a simple way you could expose the internals more, so that an external filter can be written, includng only a standard 'glfx.js' premade script.
Can someone write a basic JS version of the bulgePinch
? What I really need is just the pinch effect. I have no WebGL knowledge, so I can't write it on my own.
I've also looked at the source code of Gimp for the same effect, but again, I have no C knowledge.
Textures need to support alpha channels which works in the master branch here but in some of the new forks have broken this feature. Many new get features have been contributed by others but please be careful not to merge this regression in.
Error: WebGL warning: readPixels: Incompatible format or type. When using the getPixelArray(). I need the function getImageData() from the context how can i get this.
Could you please explain the code float amt = (mx - average) * (-amount * 3.0);,because I don't get the meaning of amt here,thanks!
Image composition effects would be awesome (effects combining multiple images). Ideas:
By the description:
var canvas = fx.canvas();
Before you can apply any filters you will need a canvas, which stores the result of the filters you apply. Canvas creation is done through fx.canvas(), which creates and returns a new WebGL tag with additional methods specific to glfx.js. This call will throw an error message if the browser doesn't support WebGL.
But
var canvas = fx.canvas();
var ctx = canvas.getContext('2d'); //Returns null
Also drawImage, getImageData, putImageData throws "not a function" error.
I want to take advantage of some effects of Glfx and also do some work on my own. For example use Glitch effect (http://snorpey.github.io/jpg-glitch/).
I want to use multiple Jquery slider for multiple filters, "Brightness / Contrast", "Denoise ", "Triangle Blur".
But applying filter is done with delay (about 1s) when the slide is fired.
this is my code:
` window.onload = function () {
var canvas = fx.canvas();
var image = document.getElementById('image');
var texture = canvas.texture(image);
$('#image').replaceWith(canvas)
canvas.draw(texture).triangleBlur(0).update();
canvas.draw(texture).denoise(50).update();
texture.destroy();
texture = canvas.contents();
$("#SliderTriangleBlur").slider({
range: "min",
min: 0,
max: 200,
value: 0,
slide: function (event, ui) {
$("#AmountTriangleBlur").val(ui.value);
var dNoise = $("#SliderDenoise").slider("option", "value");
var Brightness = $("#SliderBrightness").slider("option", "value");
var Contrast = $("#SliderContrast").slider("option", "value");
canvas.draw(texture).denoise(dNoise).brightnessContrast(Brightness, Contrast).triangleBlur(ui.value);
canvas.update();
}
});
$("#AmountTriangleBlur").val($("#SliderTriangleBlur").slider("value"));
$("#SliderDenoise").slider({
range: "min",
min: 0,
max: 50,
value: 50,
slide: function (event, ui) {
$("#AmountDenoise").val(ui.value);
var triBlur = $("#SliderTriangleBlur").slider("option", "value");
var Brightness = $("#SliderBrightness").slider("option", "value");
var Contrast = $("#SliderContrast").slider("option", "value");
canvas.draw(texture).triangleBlur(triBlur).brightnessContrast(Brightness, Contrast).denoise(ui.value);
canvas.update()
}
});
$("#AmountDenoise").val($("#SliderDenoise").slider("value"));
$("#SliderBrightness").slider({
range: "min",
min: -1,
max: 1,
step: 0.01,
value: 0,
slide: function (event, ui) {
$("#AmountBrightness").val(ui.value);
var triBlur = $("#SliderTriangleBlur").slider("option", "value");
var dNoise = $("#SliderDenoise").slider("option", "value");
var Contrast = $("#SliderContrast").slider("option", "value");
canvas.draw(texture).triangleBlur(triBlur).denoise(dNoise).brightnessContrast(ui.value, Contrast);
canvas.update()
}
});
$("#AmountBrightness").val($("#SliderBrightness").slider("value"));
$("#SliderContrast").slider({
range: "min",
min: -1,
max: 1,
step: 0.01,
value: 0,
slide: function (event, ui) {
$("#AmountContrast").val(ui.value);
var triBlur = $("#SliderTriangleBlur").slider("option", "value");
var dNoise = $("#SliderDenoise").slider("option", "value");
var Brightness = $("#SliderBrightness").slider("option", "value");
canvas.draw(texture).triangleBlur(triBlur).denoise(dNoise).brightnessContrast(Brightness, ui.value);
canvas.update();
}
});
$("#AmountContrast").val($("#SliderContrast").slider("value"));
};
`
When using the latest firefox version 79, the canvas element is just showing a black image, while it is working fine under chrome.
The browser throwing warning:
WebGL warning: checkFramebufferStatus: Using format enabled by implicitly enabled extension: WEBGL_color_buffer_float. For maximal portability enable it explicitly.
Snippet code to build the fx canvas code which is working fine at chrome
let img = new Image();
let canvas = fx.canvas();
img.onload = () => {
let texture = canvas.texture(img);
canvas.draw(texture);
canvas.update();
}
// Base64 is base64 encoded image
img.src = base64;
Is there a way to circumvent the problem?
Thanks in advance
Is there a way to set canvas width and height or other parameters before canvas.draw()? It keeps on automatically setting itself to the same size every time.
Hi, I'm trying to remove a certain color from the image after applying some filter. Is is possible to do pixel manipulation? canvas.getPixelArray()
gives me all the pixels but I can't modify and reapply them to the canvas.
Hello, thanks for Great lib! I just found one issue when using it with FF browser (18.0.2): after calling canvas.draw(texture) 1px border appears on the top and right of canvas.. You can reproduce it easily even on: http://evanw.github.com/glfx.js/demo/ with FF, just remove all styles (i did it with firebug) from canvas parent (#container) and you'll see that border i've mentioned above. Thanks!
Hi,
First of all, I love the library! it's great bud I got a small question. I know a issue like this was already posted before, bud I got the same issue. Basically, I change the contrast of an image, then I save the image as a file. It displays great bud when i open the saved file, it's psychedelic, and it isn't applied everywhere. You said on the other issue that it was something about inverting RGB vs BRG or something like that. I'm not a specialist in the field ^^'. I have the problem with contrast only. When I apply contrast on the image, and i save it, it's not the expected result.
I'm attaching an example with original, printscreen of canvas, and saved file so you can see the differences.
EDIT:
Here's the code that get the data :
var dataURL = canvas.toDataURL("image/png");
var base64 = dataURL.replace(/^data:image/(png|jpg);base64,/, "");
FYI :
OS: Win 7 SP1
Browser: Chrome 27
Graphic Card: ATI 5650M (not sure it's usefull)
Thanks for your response
I'd like to be able to apply the vignette effect in more colors than black (only black is currently supoported). Does anybody have enough webGL skills to change the vignette shader so that is supports color? I'd propose to add a 3rd color
argument to the vignette function, that accepts either a HEX or a RGB(A) color.
function vignette(size, amount /* , color */) {
gl.vignette = gl.vignette || new Shader(null, `
uniform sampler2D texture;
uniform float size;
uniform float amount;
varying vec2 texCoord;
void main() {
vec4 color = texture2D(texture, texCoord);
float dist = distance(texCoord, vec2(0.5, 0.5));
color.rgb *= smoothstep(0.8, size * 0.799, dist * (amount + size));
gl_FragColor = color;
}
`);
simpleShader.call(this, gl.vignette, {
size: clamp(0, size, 1),
amount: clamp(0, amount, 1)
});
return this;
}
Hi Evan,
I'm the creator of dcraw.js, a pure javascript viewer for Camera RAW files. Right now, dcraw.js is an emscripten port of dcraw.c with a little abstraction layer on top of it. Unfortunately its low performance makes it pretty unusable. I want to improve this by doing the parsing of the raw file in Javascript, but the whole interpolation/demosaicing (http://en.wikipedia.org/wiki/Demosaicing ) in WebGL.
Do you know of any ressources/tutorials for developing such filters?
The shaders used by the denoise and blur filters are quite heavy, and can cause a mobile GPU that can't match its desktop cousins' performance to hit a robustness timeout, especially if the filters are applied to a larger bitmap. This causes the context to be lost, and there seems to be no recovery mechanism for this app. To fix this, it would be possible to tile the bitmap up into smaller regions, and apply the filter separately to each tile, flushing between draw calls so that the commands get executed individually. Of course this costs some performance, so a compromise between a wider array of supported devices and performance has to be made.
The issue should be reproducible at least with the denoise filter on Nexus 7 with Firefox, possibly also Chrome.
A gaussian blur is an obvious addition for a library like this. A really easy (although far from the most efficient) implementation is just two iterations of a triangle blur.
Ever considered making your effects work on a portion of an image?
Your glfx library is pretty awesome so I won't link to my semi-working version. In mine, I implemented functionality to section off a portion of an image to blur. Selecting a box or circle of an image to blur.
i.e. Image that is 400 x 600
blur( image, destination, blurRadius, boxTopLeft, boxTopRight )
or
blur( image, destination, blurRadius, centerX, centerY, boxRadius )
hi,
on my safair,
toDataURL() got data be image src attr,
but, its had overturn
who can give a suggest to fix it.
thanks
@evanw I am willing to offer long term and active support for this project if that is fine with you.
I'm considering:
As glfx is using webgl inside it, i'm not able to perform zoom in/out functionality in the canvas on which images are getting change on every second.
Starting in Chrome 28 there is an issue with a warning being thrown in the GLFX demo. I've been researching, and after narrowing things down, it seems to be that a texture may be being bound to the GL context, but not being used. Unfortunately, that's as far as I've gotten in the past two hours ;) I'll probably tackle again in a few weeks, but wanted to post here too in case someone has any ideas in the meantime.
I am impressed with this library.
What it's missing for me, is a levels filter https://docs.gimp.org/en/gimp-tool-levels.html
Do you plan to add this kind of filter?
Is there a way to use tint filter on image or canvas, I have gone through the documentation but was unable to find tint filter. Can we implement tint using this library?
I've seen that the demo doesn't actually work in chrome 26 for Windows 7 (it just shows a black rectangle). Are there any plans about fixing this?
I'm trying to export an image from the canvas using canvas.toDataURL()
. This does not work for me on Chrome nor Firefox. Also the 'canvas.toDataURL.html' test does not show a second exported image.
How to export or save a screenshot of the canvas the right way?
I was having a tough time with a few cliparts of my own that had partially transparent pixels (only in IE).
After a lot of googling, I came across:
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
It seems to have done the trick. I was going to submit a PR, but wasn't sure where the best place to do it was. initialize() in the canvas.js file is probably a safe bet, and if you agree I can quickly send a PR.
To run things like gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
, I need access to the gl
variable, but that's stuck in a local context. Can we append it to the canvas object so it can be accessed from outside when needed?
Hi, I hope there is still someone here to answer some questions if so, thank you in advance.
I am using the glfx.js library in order to use matrix transformation to create the perspective effect for my images. In my app, the system works just like photoshop's smart objects (where you render a flat image and get perspective results after render)
My issue is that if the resulting image that I want after the transformation applied to the image, is bigger than the original image (happens if you rotate the image) then the WebGL canvas is going to crop my image.
Look at the following fiddle:
https://jsfiddle.net/human_a/o4yrheeq/
Any ideas on how we can make the WebGL canvas fit the rotated image (and not make the image smaller) or somehow extract the whole image instead of the cropped one?
Does glfx also work on Multi-megapixel images or is there a size limit?
I like this project very much, but it gets harder and harder to use.
Just check the forks, two of them remarcable:
It seems like the color values of transparent pixels aren't cancelled out for triangle blur. This can cause unwanted outlines as completely transparent pixels are usually represented by black or white.
Hi,
First, I wanted to thank you for your work. Man, what a great lib !
And the small modification was to bypass the modified "canvas.toDataURL" method. I explain myself. I encountered a problem (and perhaps others will too) after applying the following filters: brightness/contrast , hue saturation, unsharp mask (I didn't tested all of the filters but those 3 were obvious). Once I applied the filter, I want to retrieve the base64 content and I was surprised to detect a big difference between the content itself and the resulted code after calling canvas.toDataURL . The result is that after I saved into a image file (png or jpeg) is kind of psychedelic :-) It's not very ugly, but it's not the expected result :-)
So, I saw that you use your own function for "toDataURL". So to be sure I just commented the following line: // canvas.toDataURL = wrap(toDataURL); (in my generated code (non-compressed) it's on line 556 ) and the image gets saved correctly...
Hope it helps others having the same result ..
PS: Really nice work. Thank you !
Since Google updated Chrome to version 24 glfx.js (and all your WebGL-related libraries such as webgl-filter) no longer work on Windows (at least Vista and 7), it simply appears completely black, nothing is rendered to the context at all. I've tried to pin this bug down and it's something wrong in either Texture.prototype.drawTo or Shader.prototype.drawRect. There's no problem on OS X.
It only seems to affect some Windows machines, but I am able to reproduce this on my own test laptop Windows PC. The demo at http://evanw.github.com/webgl-filter/ shows nothings but a black rectangle.
This could relate to an ANGLE update in Chrome 24, an issue for which is here: https://code.google.com/p/chromium/issues/detail?id=172278
Please let me know if there's anything I can do to help fix this!
Paul.
I'm trying to export an image from the canvas using canvas.toDataURL()
. However I got a transparent image, and I find a way to fix it(http://stackoverflow.com/questions/12538193/why-does-my-canvas-go-blank-after-converting-to-image).
exports.canvas = function () {
var canvas = document.createElement('canvas');
var setting = { premultipliedAlpha: false, preserveDrawingBuffer: true };
try {
gl = canvas.getContext('webgl', setting) || canvas.getContext('experimental-webgl', setting);
} catch (e) {
gl = null;
}
if (!gl) {
throw 'This browser does not support WebGL';
}
// ...
}
Hello,
I use glfx to switch between different images on the created canvas. That's working so far.
But I also want to have a smooth fading effect when the images are switching.
For canvas there is a method called globalAlpha which can be assigned to a 2d context of a canvas.
Sadly glfx creates a canvas with a webgl context and I cannot assign a second context to that canvas.
So how can I use globalAlpha on my glfx canvas? Or is there another simple method (for switching with fade) which can be used in combination with glfx?
Any suggestions are appreciated. Thx :)
Thanks for glfx, it's a really nice library!
I wonder if zoom in/ out is/ can be a filter -- or should I manipulate the directly to get the zoom feature?
Hi!
When using multiple instances and updating textures the global active context can be wrong if loadContentsOf is fired before the global context has been updated. I solved it by adding a parameter to the texture object and assign it in the wrapper.
In the Texture constructor:
this.gl = gl;
and modify this method:
function wrapTexture(texture) {
return {
_: texture,
loadContentsOf: function(element) {
//set correct global gl
gl = this._.gl;
this._.loadContentsOf(element);
},
clear: function() { this._.clear(); },
width: function() { return this._.width; },
height: function() { return this._.height; },
destroy: function() { this._.destroy(); }
};
}
/ Einar
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.