HTML5 canvas filters on images
Remember these codes work only with ie emulation as pointed in previous posts (otherwise have fired errors when running).These codes are tested on IE11 emulation.
JavaScript is still essential to work with canvas.
I used a mixed code vfp/javascript to work with canvas because the DOM way dont work as well with vfp (see also the previous posts).
Instead a vfp form i use this once an internet explorer application whose can access to the fullscreen easily.
Important : to avoid some problems with IE run vfp always as administrator.
With html5 canvas can draw any image with any dimensions specified. This drawimage function desserves also the resize operation of original image to any dimensions. Can apply filters on any image drawn as follow -a linear gradient object with many colors.The colors can be transparent with applying rgba (alpha channel used) for this purpose. -A radial gradient object with many colors.The colors can be also transparent with applying RGBA( and its alpha channel). -Any rgba color with the alpha channel tranparent (transparency between 0-1). this code uses theses idea to make a filter on image and capture the entier compound as image the code uses the context ('2d') property: ctx.globalCompositeOperation = "destination-over"; see some screenshots below.
*1*apply a transparent filter gradient on any image.
Declare Integer BringWindowToTop In user32 Integer
Declare Integer SetWindowText In user32 Integer HWnd, String lpstring
Declare Integer Sleep In kernel32 Integer
Publi apie
apie=Newobject("internetexplorer.application")
apie.Navigate("about:blank")
Sleep(500)
With apie
TEXT to m.myvar textmerge noshow
<body topmargin=0 leftmargin=0 bgcolor="black" scroll="no" oncontextmenu="window.close();return false;" >
<canvas id="ycanvas1" width="<<sysmetric(1)>>" height="<<sysmetric(2))>>" ></canvas>
</body>
ENDTEXT
.Document.body.outerhtml=.Document.body.outerhtml+m.myvar
Endwith
Local m.xpict
m.xpict=Getpict()
If Empty(m.xpict)
Return .F.
Endi
m.xpict=Strtran(m.xpict,'\','/')
Local m.rep,m.xx
m.rep=Int(Val(Inputbox("LinearGradient (1) or radialgradient(2) or color(3)","choose gradient/color","1")))
If !Between(m.rep,1,3)
m.rep=1
Endi
Do Case
Case m.rep=1
TEXT to m.xx noshow
var my_gradient=ctx.createLinearGradient(0,0,canvas.width,0);
my_gradient.addColorStop(0, "rgba(0, 215, 0, 0.75)");
my_gradient.addColorStop(0.3,"rgba(205, 0, 0, 0.5)");
my_gradient.addColorStop(0.5,"rgba(105, 0, 205, 0.3)");
my_gradient.addColorStop(0.7,"rgba(0, 215, 205, 0.5)");
my_gradient.addColorStop(1,"rgba(205, 215, 0, 0.5)");
ctx.fillStyle=my_gradient;
ENDTEXT
Case m.rep=2
TEXT to m.xx noshow
var my_gradient=ctx.createRadialGradient(canvas.width/2,canvas.height/2,50,canvas.width/2,canvas.height/2,canvas.width/2);
my_gradient.addColorStop(0, "rgba(0, 215, 0, 0.75)");
my_gradient.addColorStop(0.3,"rgba(205, 0, 0, 0.5)");
my_gradient.addColorStop(0.5,"rgba(105, 0, 205, 0.3)");
my_gradient.addColorStop(0.7,"rgba(0, 215, 205, 0.5)");
my_gradient.addColorStop(1,"rgba(205, 215, 0, 0.5)");
ctx.fillStyle=my_gradient;
ENDTEXT
Case m.rep=3
Local xcolor
m.xcolor=Getcolor()
If Empty(m.xcolor)
m.xcolor=Rgb(0,255,0)
Endi
Local RGBChr,r,g,b,ycolor
m.RGBChr=Left(BinToC(m.xcolor,'R'),3)
r=Asc(Substr(m.RGBChr,1,1)) && RED
g=Asc(Substr(m.RGBChr,2,1)) && GREEN
b=Asc(Substr(m.RGBChr,3,1)) && BLUE
ycolor='rgba('+Trans(r,'999')+','+Trans(g,"999")+','+Trans(b,'999')+',0.5)'
TEXT to m.xx textmerge noshow
ctx.fillStyle='<<m.ycolor>>';
ENDTEXT
Endcase
TEXT to m.myvar textmerge noshow
var canvas=document.getElementById("ycanvas1");
canvas.style.background="black";
var ctx = canvas.getContext("2d");
img=new Image();
img.src=' <<xpict>> ' ;
img.onload = function () {
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
}
ctx.globalCompositeOperation = "destination-over";
<<m.xx>>
ctx.fillRect(0,0,canvas.width,canvas.height);
ENDTEXT
With apie.Document
x=.createElement("SCRIPT")
x.Id="yscript"
T =.createTextNode(m.myvar)
x.appendChild(T)
.body.appendChild(x)
Endwith
Sleep(2000)
*_cliptext=m.myvar
With apie
.menubar=0
.Toolbar=0
.StatusBar=0
*if want a normal window (adapt dimensions)
*.width=800
*.height=600
*.top=50
*.left=(sysmetric(1)-.width)/2
.fullscreen=1
BringWindowToTop(.HWnd)
SetWindowText(.HWnd, "Html5 canvas image with transparent gradient")
.Visible=.T.
Local m.mess
TEXT to m.mess noshow
-Right click or CTRL+F4 to close the fullscreen window!
-The screen capture is in clipboard-Run MSPAINt and paste it as
(PNG,JPG,BMP,GIF...)
ENDTEXT
Messagebox(m.mess,0+32+4096,'',1500)
Sleep(500)
ycap()
Endwith
Retu
Function ycap()
Declare Integer keybd_event In Win32API INTEGER, Integer, Integer, Integer
VK_SNAPSHOT = 44 && from the winuser.h
VK_LMENU = 164
KEYEVENTF_KEYUP = 2
KEYEVENTF_EXTENDEDKEY = 1
DoEvents
keybd_event(VK_SNAPSHOT, 1, 0, 0 )
keybd_event(VK_SNAPSHOT, 1, KEYEVENTF_KEYUP, 0 )
DoEvents
Inkey(0.5)
*if want to show Mspaint and the captured picture pasted on
*_screen.windowstate=1
*run/n3 "mspaint"
*inkey(2)
*oshell=createObject("wscript.shell")
*oshell.sendkeys("^{v}")
Endfunc
This uses a transparent filter build with random rectangles with random fills and random strokes and transparency with alpha channel.
Its applied on the image drawn on the canvas with the context('2d') property:
*2* apply a transparent multi rectangles colored filter on any image.
Declare Integer BringWindowToTop In user32 Integer
Declare Integer SetWindowText In user32 Integer HWnd, String lpstring
Declare Integer Sleep In kernel32 Integer
Publi apie
apie=Newobject("internetexplorer.application")
apie.Navigate("about:blank")
Sleep(500)
With apie
TEXT to m.myvar textmerge noshow
<body topmargin=0 leftmargin=0 bgcolor="black" scroll="no" oncontextmenu="window.close();return false;" >
<canvas id="ycanvas1" width="<<sysmetric(1)>>" height="<<sysmetric(2)>>" ></canvas>
</body>
ENDTEXT
.Document.body.outerhtml=.Document.body.outerhtml+m.myvar
Endwith
Local m.xpict
m.xpict=Getpict()
If Empty(m.xpict)
Return .F.
Endi
m.xpict=Strtran(m.xpict,'\','/')
Local x0,y0,w,h, gnLower,gnUpper
gnLower=0
gnUpper=Sysmetric(1)-5
x0= Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
y0=Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
gnLower=50
gnUpper=200
w=Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
h=Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
TEXT to m.myvar textmerge noshow
var canvas=document.getElementById("ycanvas1");
canvas.style.background="black";
var ctx = canvas.getContext("2d");
img=new Image();
img.src=' <<xpict>> ' ;
img.onload = function () {
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
}
ctx.globalCompositeOperation = "destination-over";
for (var i = 0; i < 1000; i++) {
var rr=Math.floor(Math.random()*255);
var gg=Math.floor(Math.random()*255);
var bb=Math.floor(Math.random()*255);
var alpha1=0.07; //Math.random();
var col= 'rgba('+rr+','+gg +','+bb+','+alpha1+')';
ctx.fillStyle=col;
var min = 0;
var max = <<sysmetric(1)>>;
var x0 = Math.floor(Math.random() * (max - min + 1)) + min;
var y0 = Math.floor(Math.random() * (max - min + 1)) + min;
var w=Math.floor(Math.random() * (200 - 50 + 1)) + min;
var h=Math.floor(Math.random() * (200 - 50 + 1)) + min;
ctx.fillRect(x0,y0,w,h);
}
ENDTEXT
With apie.Document
x=.createElement("SCRIPT")
x.Id="yscript"
T =.createTextNode(m.myvar)
x.appendChild(T)
.body.appendChild(x)
Endwith
Sleep(2000)
With apie
.menubar=0
.Toolbar=0
.StatusBar=0
*if want a noram window
*.width=800
*.height=600
*.top=50
*.left=(sysmetric(1)-.width)/2
.fullscreen=1
Local m.mess
TEXT to m.mess noshow
-The picture is captured in clipboard-Run MsPaint and
paste it....save as (png,jpg,gif,bmp...)
-Rightclick or CTRL+F4 to close the window.
ENDTEXT
Messagebox(m.mess,0+32+4096,"",1500)
BringWindowToTop(.HWnd)
SetWindowText(.HWnd, "Html5 canvas image with transparent gradient")
.Visible=.T.
Sleep(700)
ycap()
Endwith
Retu
Function ycap()
Declare Integer keybd_event In Win32API INTEGER, Integer, Integer, Integer
VK_SNAPSHOT = 44 && from the winuser.h
VK_LMENU = 164
KEYEVENTF_KEYUP = 2
KEYEVENTF_EXTENDEDKEY = 1
DoEvents
keybd_event(VK_SNAPSHOT, 1, 0, 0 )
keybd_event(VK_SNAPSHOT, 1, KEYEVENTF_KEYUP, 0 )
DoEvents
Inkey(0.5)
*if want to show Mspaint with a pasted picture captured
*_screen.windowstate=1
*run/n3 "mspaint"
*inkey(2)
*oshell=createObject("wscript.shell")
*oshell.sendkeys("^{v}")
Endfunc
*3*apply a transparent multi circles colored filter on any picture.
*it uses the same code as rectangles but with circles and contrours.
Declare Integer BringWindowToTop In user32 Integer
Declare Integer SetWindowText In user32 Integer HWnd, String lpstring
Declare Integer Sleep In kernel32 Integer
Publi apie
apie=Newobject("internetexplorer.application")
apie.Navigate("about:blank")
Sleep(500)
With apie
TEXT to m.myvar textmerge noshow
<body topmargin=-20 leftmargin=0 bgcolor="black" scroll="no" oncontextmenu="window.close();return false;" >
<canvas id="ycanvas1" width="<<sysmetric(1)>>" height="<<sysmetric(2)>>" ></canvas>
</body>
ENDTEXT
.Document.body.outerhtml=.Document.body.outerhtml+m.myvar
Endwith
Local m.xpict
m.xpict=Getpict()
If Empty(m.xpict)
Return .F.
Endi
m.xpict=Strtran(m.xpict,'\','/')
Local m.rep,m.xx
m.rep=Inputbox("draw circles contours (yes-no)?","","no")
If !Inlist(m.rep,"yes","no")
m.rep="no"
Endi
If m.rep="yes"
TEXT to m.xx noshow
ctx.lineWidth=1;
rr=Math.floor(Math.random()*255);
gg=Math.floor(Math.random()*255);
bb=Math.floor(Math.random()*255);
alpha1=0.25*Math.random();
col= 'rgba('+rr+','+gg +','+bb+','+alpha1+')';
ctx.strokeStyle=col;
ctx.stroke();
ENDTEXT
Else
m.xx=""
Endi
Local x0,y0,w,h, gnLower,gnUpper
gnLower=0
gnUpper=Sysmetric(1)-5
x0= Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
y0=Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
gnLower=50
gnUpper=150
w=Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
*h=Int((gnUpper - gnLower + 1) * Rand( ) + gnLower)
TEXT to m.myvar textmerge noshow
var canvas=document.getElementById("ycanvas1");
canvas.style.background="black";
var ctx = canvas.getContext("2d");
img=new Image();
img.src=' <<xpict>> ' ;
img.onload = function () {
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
}
ctx.globalCompositeOperation = "destination-over";
for (var i = 0; i < 1000; i++) {
var rr=Math.floor(Math.random()*255);
var gg=Math.floor(Math.random()*255);
var bb=Math.floor(Math.random()*255);
var alpha1=0.04; //Math.random();
var col= 'rgba('+rr+','+gg +','+bb+','+alpha1+')';
ctx.fillStyle=col;
var min = 0;
var max = <<sysmetric(1)>>;
var x0 = Math.floor(Math.random() * (max - min + 1)) + min;
var y0 = Math.floor(Math.random() * (max - min + 1)) + min;
var w=Math.floor(Math.random() * (200 - 50 + 1)) + min;
var h=Math.floor(Math.random() * (200 - 50 + 1)) + min;
// draw transparent circle
ctx.beginPath();
ctx.arc(x0, y0, w, 0, 2 * Math.PI, false);
ctx.fill();
<<m.xx>>
}
ENDTEXT
With apie.Document
x=.createElement("SCRIPT")
x.Id="yscript"
T =.createTextNode(m.myvar)
x.appendChild(T)
.body.appendChild(x)
Endwith
Sleep(2000)
*_cliptext=m.myvar
With apie
.menubar=0
.Toolbar=0
.StatusBar=0
*If want a not fullscreen view
*.width=800
*.height=600
*.top=50
*.left=(sysmetic(1)-.width)/2
.fullscreen=1
Local m.mess
TEXT to m.mess noshow
-The picture is captured in clipboard-Run MsPaint and
paste it....save as (png,jpg,gif,bmp...)
-Rightclick or CTRL+F4 to close the window.
ENDTEXT
Messagebox(m.mess,0+32+4096,"",1500)
BringWindowToTop(.HWnd)
SetWindowText(.HWnd, "Html5 canvas image with transparent gradient")
.Visible=.T.
Sleep(700)
ycap()
Endwith
Retu
Function ycap()
Declare Integer keybd_event In Win32API INTEGER, Integer, Integer, Integer
VK_SNAPSHOT = 44 && from the winuser.h
VK_LMENU = 164
KEYEVENTF_KEYUP = 2
KEYEVENTF_EXTENDEDKEY = 1
DoEvents
keybd_event(VK_SNAPSHOT, 1, 0, 0 )
keybd_event(VK_SNAPSHOT, 1, KEYEVENTF_KEYUP, 0 )
DoEvents
Inkey(0.5)
*if want to show MSPAINT+picture pasted
*_screen.windowstate=1
*run/n3 "mspaint"
*inkey(2)
*oshell=createObject("wscript.shell")
*oshell.sendkeys("^{v}")
Endfunc
This code below is similar to the first above but all is built in the web page.it generates a filter on any image as :
-lineargradient with 7 random colors with transparency in alpha channel
-radialgradient with 7 random colors
-unique random color with
can press reset button to change the colors
can save the picture as PNG or print it.
*4*apply a transparent random filter gradient on any image.
* -random lineargradient,random Radial Gradient-random color
Set Safe Off
Declare Integer BringWindowToTop In user32 Integer
Declare Integer SetWindowText In user32 Integer HWnd, String lpstring
Declare Integer Sleep In kernel32 Integer
Local m.xpict
m.xpict=Getpict()
If Empty(m.xpict)
Return .F.
Endi
m.xpict=Strtran(m.xpict,'\','/')
TEXT to m.myvar noshow
<!DOCTYPE html>
<html>
<head>
<title>Html5 canvas: Applying filters on image</title>
</head>
<body>
</body>
</html>
ENDTEXT
m.lcdest=Addbs(Sys(2023))+"test.html"
Strtofile(m.myvar, m.lcdest)
Publi apie
apie=Newobject("internetexplorer.application")
apie.Navigate(m.lcdest)
Sleep(500)
With apie
TEXT to m.myvar textmerge noshow
<body topmargin=0 leftmargin=0 bgcolor="black" scroll="no" oncontextmenu="window.close();return false;" >
<canvas id="ycanvas1" width="<<sysmetric(1)>>" height="<<sysmetric(2)-30>>" ></canvas>
<br>
<center>
<input type="button" id="yb" value="Reset" style="background-color:lime;color:red" onclick="init();">
<input type="button" id="ysave" value="Save As" style="background-color:lime;color:red" onclick="saveImageAs();">
<input type="button" id="yquit" value="Exit" style="background-color:lime;color:red" onclick="window.close();">
</center>
</body>
ENDTEXT
.Document.body.outerhtml=.Document.body.outerhtml+m.myvar
Endwith
Local m.rep,m.xx
m.rep=Int(Val(Inputbox("LinearGradient (1) or radialgradient(2) or color(3)","choose gradient/color","1")))
If !Between(m.rep,1,3)
m.rep=1
Endi
Do Case
Case m.rep=1
TEXT to m.xx noshow
var my_gradient=ctx.createLinearGradient(0,0,canvas.width,0);
my_gradient.addColorStop(0, randomcolor());
my_gradient.addColorStop(0.3,randomcolor());
my_gradient.addColorStop(0.5,randomcolor());
my_gradient.addColorStop(0.7,randomcolor());
my_gradient.addColorStop(1,randomcolor());
ctx.fillStyle=my_gradient;
ENDTEXT
Case m.rep=2
TEXT to m.xx noshow
var my_gradient=ctx.createRadialGradient(canvas.width/2,canvas.height/2,50,canvas.width/2,canvas.height/2,canvas.width/2);
my_gradient.addColorStop(0, randomcolor());
my_gradient.addColorStop(0.3,randomcolor());
my_gradient.addColorStop(0.5,randomcolor());
my_gradient.addColorStop(0.7,randomcolor());
my_gradient.addColorStop(1,randomcolor());
ctx.fillStyle=my_gradient;
ENDTEXT
Case m.rep=3
TEXT to m.xx textmerge noshow
ctx.fillStyle = "rgba(" + Math.round(255 * Math.random()) + ","
+ Math.round(255 * Math.random()) + ","
+ Math.round(255 * Math.random()) + ",0.5)";
ENDTEXT
Endcase
TEXT to m.myvar textmerge noshow
function init(){
var canvas=document.getElementById("ycanvas1");
canvas.style.background="black";
var ctx = canvas.getContext("2d");
ctx.fillStyle="000000";
ctx.clearRect(0,0,canvas.width,canvas.height);
img=new Image();
img.src=' <<xpict>> ' ;
img.onload = function () {
ctx.drawImage(img, 0, 0,canvas.width,canvas.height);
}
ctx.globalCompositeOperation = "destination-over";
<<m.xx>>
ctx.fillRect(0,0,canvas.width,canvas.height);
}
init();
function randomcolor(){
return "rgba(" + Math.round(255 * Math.random()) + ","
+ Math.round(255 * Math.random()) + ","
+ Math.round(255 * Math.random()) + ",0.5)";
}
function saveImageAs (){
var c=document.getElementById("ycanvas1");
var d=c.toDataURL("image/png");
alert(d);
var w=window.open('about:blank','','menubar=0, titlebar=0,statusbar=0,width=850,height=650,resizable=1');
w.document.write('<h2 style="background-color:yellow;color:maroon;width:450;">Right click to save image or print<h2><br>'+"<img src='"+d+"' alt='from canvas'/>");
}
ENDTEXT
With apie.Document
x=.createElement("SCRIPT")
x.Id="yscript"
T =.createTextNode(m.myvar)
x.appendChild(T)
.body.appendChild(x)
Endwith
Sleep(2000)
With apie
.menubar=0
.Toolbar=0
.StatusBar=0
*if want a normal window (adapt dimensions)
*.width=800
*.height=600
*.top=50
*.left=(sysmetric(1)-.width)/2
.fullscreen=1
SetWindowText(.HWnd, "Html5 canvas image with transparent gradient")
Local m.mess
TEXT to m.mess noshow
-Right click or CTRL+F4 to close the fullscreen window (or simply click 'exit' button!
-can change the random gradients(linear,radial,or colors) by the button 'reset'
-can save the image as PNG (or pint it).click the button 'save'
ENDTEXT
Messagebox(m.mess,0+32+4096,2000)
BringWindowToTop(.HWnd)
.Visible=.T.
Endwith
Retu