Example of six special filter effects for HTML5 Canvas implemented using pure JavaScript

Source: Internet
Author: User

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
}
}
},
};

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.