The experiment demonstrates how to implement six simple and common HTML5 Canvas Special filter effects and encapsulate them into a pure JavaScript callable API file gloomyfishfilter. js.The following special filter effects are supported:
1. Reversed colors
2. Gray Adjustment
3. Fuzzy
4. Relief
5. Carving
6. Images
Filter Principle explanation:
1. Reversed color: Obtain the RGB value r, g, and B of A pixel. The new RGB value is (255-r, 255-g, 255-b)
2. gray tone: Obtain the RGB value r, g, and B of A pixel. The new RGB value is
Copy codeThe Code is as follows:
Newr = (r * 0.272) + (g * 0.534) + (B * 0.131 );
Newg = (r * 0.349) + (g * 0.686) + (B * 0.168 );
Newb = (r * 0.393) + (g * 0.769) + (B * 0.189 );
3. Fuzzy: A 5*5 convolution kernel
4. Relief and carving:
The difference between the RGB value of the first pixel and the RGB value of the last pixel is 128
5. Image: simulates the effect of an object in the mirror.
Miscellaneous preparation
1. How to obtain the Canvas 2d context object
Copy codeThe Code is as follows:
Var canvas = document. getElementById ("target ");
Canvas. width = source. clientWidth;
Canvas. height = source. clientHeight;
If (! Canvas. getContext ){
Console. log ("Canvas not supported. Please install a HTML5compatible browser .");
Return;
}
// Get 2D context of canvas and draw image
TempContext = canvas. getContext ("2d ");
2. How to draw a DOM img object to a Canvas object
Copy codeThe Code is as follows:
Var source = document. getElementById ("source ");
TempContext. drawImage (source, 0, 0, canvas. width, canvas. height );
3. How to obtain pixel data from a Canvas object
Copy codeThe Code is as follows:
Var canvas = document. getElementById ("target ");
Varlen = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
Var binaryData = canvasData. data;
4. How to bind a mouse Click event to a DOM object
Copy codeThe Code is as follows:
Function bindButtonEvent (element, type, handler)
{
If (element. addEventListener ){
Element. addEventListener (type, handler, false );
} Else {
Element. attachEvent ('on' + type, handler); // for IE6, 7,8
}
}
5. How to call the implemented gfilter API to complete the filter function
Copy codeThe Code is as follows:
<Scriptsrc = "gloomyfishfilter. js"> </script> // import an API File
Gfilter. colorInvertProcess (binaryData, len); // call the API
6. browser support: IE, FF, and Chrome are successfully tested. IE supports the following labels:
Copy codeThe Code is as follows:
<Meta http-equiv = "X-UA-Compatible" content = "chrome = IE8">
Demo:
Application source code:
CSS section:
Copy codeThe Code is as follows:
# SvgContainer {
Width: 800px;
Height: 600px;
Background-color: # EEEEEE;
}
# SourceDiv {float: left; border: 2px solid blue}
# TargetDiv {float: right; border: 2px solid red}
HTML source code in filter1.html:
Copy codeThe Code is as follows:
<! DOCTYPE html>
<Html>
<Head>
<Meta http-equiv = "X-UA-Compatible" content = "chrome = IE8">
<Meta http-equiv = "Content-type" content = "text/html; charset = UTF-8">
<Title> Canvas Filter Demo </title>
<Link href = "default.css" rel = "stylesheet"/>
<Script src = "gloomyfishfilter. js"> </scrip>
</Head>
<Body>
<H1> HTML Canvas Image Process-By Gloomy Fish <Div id = "svgContainer">
<Div id = "sourceDiv">
</Div>
<Div id = "targetDiv">
<Canvas id = "target"> </canvas>
</Div>
</Div>
<Div id = "btn-group">
<Button type = "button" id = "invert-button"> reversed </button>
<Button type = "button" id = "adjust-button"> gray tone </button>
<Button type = "button" id = "blur-button"> fuzzy </button>
<Button type = "button" id = "relief-button"> relief </button>
<Button type = "button" id = "diaoke-button"> carving </button>
<Button type = "button" id = "mirror-button"> image </button>
</Div>
</Body>
</Html>
JavaScript source code in filter1.html:
Copy codeThe Code is as follows:
Var tempContext = null; // global variable 2d context
Window. onload = function (){
Var source = document. getElementById ("source ");
Var canvas = document. getElementById ("target ");
Canvas. width = source. clientWidth;
Canvas. height = source. clientHeight;
If (! Canvas. getContext ){
Console. log ("Canvas not supported. Please install a HTML5 compatible browser .");
Return;
}
// Get 2D context of canvas and draw image
TempContext = canvas. getContext ("2d ");
TempContext. drawImage (source, 0, 0, canvas. width, canvas. height );
// Initialization actions
Var inButton = document. getElementById ("invert-button ");
Var adButton = document. getElementById ("adjust-button ");
Var blurButton = document. getElementById ("blur-button ");
Var reButton = document. getElementById ("relief-button ");
Var dkButton = document. getElementById ("diaoke-button ");
Var mirrorButton = document. getElementById ("mirror-button ");
// Bind mouse click event
BindButtonEvent (inButton, "click", invertColor );
BindButtonEvent (adButton, "click", adjustColor );
BindButtonEvent (blurButton, "click", blurImage );
BindButtonEvent (reButton, "click", fudiaoImage );
BindButtonEvent (dkButton, "click", kediaoImage );
BindButtonEvent (mirrorButton, "click", mirrorImage );
}
Function bindButtonEvent (element, type, handler)
{
If (element. addEventListener ){
Element. addEventListener (type, handler, false );
} Else {
Element. attachEvent ('on' + type, handler); // for IE6, 7,8
}
}
Function invertColor (){
Var canvas = document. getElementById ("target ");
Var len = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
Var binaryData = canvasData. data;
// Processing all the pixels
Gfilter. colorInvertProcess (binaryData, len );
// Copying back canvas data to canvas
TempContext. putImageData (canvasData, 0, 0 );
}
Function adjustColor (){
Var canvas = document. getElementById ("target ");
Var len = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
Var binaryData = canvasData. data;
// Processing all the pixels
Gfilter. colorAdjustProcess (binaryData, len );
// Copying back canvas data to canvas
TempContext. putImageData (canvasData, 0, 0 );
}
Function blurImage ()
{
Var canvas = document. getElementById ("target ");
Var len = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
// Processing all the pixels
Gfilter. blurProcess (tempContext, canvasData );
// Copying back canvas data to canvas
TempContext. putImageData (canvasData, 0, 0 );
}
Function fudiaoImage ()
{
Var canvas = document. getElementById ("target ");
Var len = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
// Processing all the pixels
Gfilter. reliefProcess (tempContext, canvasData );
// Copying back canvas data to canvas
TempContext. putImageData (canvasData, 0, 0 );
}
Function kediaoImage ()
{
Var canvas = document. getElementById ("target ");
Var len = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
// Processing all the pixels
Gfilter. diaokeProcess (tempContext, canvasData );
// Copying back canvas data to canvas
TempContext. putImageData (canvasData, 0, 0 );
}
Function mirrorImage ()
{
Var canvas = document. getElementById ("target ");
Var len = canvas. width * canvas. height * 4;
Var canvasData = tempContext. getImageData (0, 0, canvas. width, canvas. height );
// Processing all the pixels
Gfilter. merge process (tempContext, canvasData );
// Copying back canvas data to canvas
TempContext. putImageData (canvasData, 0, 0 );
}
Filter source code (gloomyfishfilter. js ):
Copy codeThe Code is as follows:
Var gfilter = {
Type: "canvas ",
Name: "filters ",
Author: "zhigang ",
GetInfo: function (){
Return this. author + ''+ this. type +'' + this. name;
},
/**
* Invert color value of pixel, new pixel = RGB (255-r, 255-g, 255-B)
*
* @ Param binaryData-canvas's imagedata. data
* @ Param l-length of data (width * height of image data)
*/
ColorInvertProcess: function (binaryData, l ){
For (var I = 0; I <l; I + = 4 ){
Var r = binaryData [I];
Var g = binaryData [I + 1];
Var B = binaryData [I + 2];
BinaryData [I] = 255-r;
BinaryData [I + 1] = 255-g;
BinaryData [I + 2] = 255-b;
}
},
/**
* Adjust color values and make it more darker and gray...
*
* @ Param binaryData
* @ Param l
*/
ColorAdjustProcess: function (binaryData, l ){
For (var I = 0; I <l; I + = 4 ){
Var r = binaryData [I];
Var g = binaryData [I + 1];
Var B = binaryData [I + 2];
BinaryData [I] = (r * 0.272) + (g * 0.534) + (B * 0.131 );
BinaryData [I + 1] = (r * 0.349) + (g * 0.686) + (B * 0.168 );
BinaryData [I + 2] = (r * 0.393) + (g * 0.769) + (B * 0.189 );
}
},
/**
* Deep clone image data of canvas
*
* @ Param context
* @ Param src
* @ Returns
*/
CopyImageData: function (context, src)
{
Var dst = context. createImageData (src. width, src. height );
Dst. data. set (src. data );
Return dst;
},
/**
* Convolution-keneral size 5*5-blur effect filter (Fuzzy effect)
*
* @ Param context
* @ Param canvasData
*/
BlurProcess: function (context, canvasData ){
Console. log ("Canvas Filter-blur process ");
Var tempCanvasData = this. copyImageData (context, canvasData );
Var sumred = 0.0, sumgreen = 0.0, sumblue = 0.0;
For (var x = 0; x <tempCanvasData. width; x ++ ){
For (var y = 0; y <tempCanvasData. height; y ++ ){
// Index of the pixel in the array
Var idx = (x + y * tempCanvasData. width) * 4;
For (var subCol =-2; subCol <= 2; subCol ++ ){
Var colOff = subCol + x;
If (colOff <0 | colOff> = tempCanvasData. width ){
ColOff = 0;
}
For (var subRow =-2; subRow <= 2; subRow ++ ){
Var rowOff = subRow + y;
If (rowOff <0 | rowOff> = tempCanvasData. height ){
RowOff = 0;
}
Var idx2 = (colOff + rowOff * tempCanvasData. width) * 4;
Var r = tempCanvasData. data [idx2 + 0];
Var g = tempCanvasData. data [idx2 + 1];
Var B = tempCanvasData. data [idx2 + 2];
Sumred + = r;
Sumgreen + = g;
Sumblue + = B;
}
}
// Calculate new RGB value
Var nr = (sumred/ 25.0 );
Var ng = (sumgreen/ 25.0 );
Var nb = (sumblue/25.0 );
// Clear previous for next pixel point
Sumred= 0.0;
Sumgreen= 0.0;
Sumblue = 0.0;
// Assign new pixel value
CanvasData. data [idx + 0] = nr; // Red channel
CanvasData. data [idx + 1] = ng; // Green channel
CanvasData. data [idx + 2] = nb; // Blue channel
CanvasData. data [idx + 3] = 255; // Alpha channel
}
}
},
/**
* After pixel value-before pixel value + 128
* Embossed Effect
*/
ReliefProcess: function (context, canvasData ){
Console. log ("Canvas Filter-relief process ");
Var tempCanvasData = this. copyImageData (context, canvasData );
For (var x = 1; x <tempCanvasData. width-1; x ++)
{
For (var y = 1; y <tempCanvasData. height-1; y ++)
{
// Index of the pixel in the array
Var idx = (x + y * tempCanvasData. width) * 4;
Var bidx = (x-1) + y * tempCanvasData. width) * 4;
Var aidx = (x + 1) + y * tempCanvasData. width) * 4;
// Calculate new RGB value
Var nr = tempCanvasData. data [aidx + 0]-tempCanvasData. data [bidx + 0] + 128;
Var ng = tempCanvasData. data [aidx + 1]-tempCanvasData. data [bidx + 1] + 128;
Var nb = tempCanvasData. data [aidx + 2]-tempCanvasData. data [bidx ++ 2] + 128;
Nr = (nr <0 )? 0: (nr> 255 )? 255: nr );
Ng = (ng <0 )? 0: (ng> 255 )? 255: ng );
Nb = (nb <0 )? 0: (nb> 255 )? 255: nb );
// Assign new pixel value
CanvasData. data [idx + 0] = nr; // Red channel
CanvasData. data [idx + 1] = ng; // Green channel
CanvasData. data [idx + 2] = nb; // Blue channel
CanvasData. data [idx + 3] = 255; // Alpha channel
}
}
},
/**
* Before pixel value-after pixel value + 128
* Carving Effect
*
* @ Param canvasData
*/
DiaokeProcess: function (context, canvasData ){
Console. log ("Canvas Filter-process ");
Var tempCanvasData = this. copyImageData (context, canvasData );
For (var x = 1; x <tempCanvasData. width-1; x ++)
{
For (var y = 1; y <tempCanvasData. height-1; y ++)
{
// Index of the pixel in the array
Var idx = (x + y * tempCanvasData. width) * 4;
Var bidx = (x-1) + y * tempCanvasData. width) * 4;
Var aidx = (x + 1) + y * tempCanvasData. width) * 4;
// Calculate new RGB value
Var nr = tempCanvasData. data [bidx + 0]-tempCanvasData. data [aidx + 0] + 128;
Var ng = tempCanvasData. data [bidx + 1]-tempCanvasData. data [aidx + 1] + 128;
Var nb = tempCanvasData. data [bidx + 2]-tempCanvasData. data [aidx ++ 2] + 128;
Nr = (nr <0 )? 0: (nr> 255 )? 255: nr );
Ng = (ng <0 )? 0: (ng> 255 )? 255: ng );
Nb = (nb <0 )? 0: (nb> 255 )? 255: nb );
// Assign new pixel value
CanvasData. data [idx + 0] = nr; // Red channel
CanvasData. data [idx + 1] = ng; // Green channel
CanvasData. data [idx + 2] = nb; // Blue channel
CanvasData. data [idx + 3] = 255; // Alpha channel
}
}
},
/**
* Mirror reflect
*
* @ Param context
* @ Param canvasData
*/
Using process: function (context, canvasData ){
Console. log ("Canvas Filter-process ");
Var tempCanvasData = this. copyImageData (context, canvasData );
For (var x = 0; x <tempCanvasData. width; x ++) // column
{
For (var y = 0; y <tempCanvasData. height; y ++) // row
{
// Index of the pixel in the array
Var idx = (x + y * tempCanvasData. width) * 4;
Var midx = (tempCanvasData. width-1)-x) + y * tempCanvasData. width) * 4;
// Assign new pixel value
CanvasData. data [midx + 0] = tempCanvasData. data [idx + 0]; // Red channel
CanvasData. data [midx + 1] = tempCanvasData. data [idx + 1]; // Green channel
CanvasData. data [midx + 2] = tempCanvasData. data [idx + 2]; // Blue channel
CanvasData. data [midx + 3] = 255; // Alpha channel
}
}
},
};