How do you convert a color image to black/white using only Javascript?
AND, also make it cross compatible in most browsers because I hear Internet Explorer has a "filter" mechanism but no other browsers support it.
How do you convert a color image to black/white using only Javascript?
AND, also make it cross compatible in most browsers because I hear Internet Explorer has a "filter" mechanism but no other browsers support it.
Despite my initial scepticism it appears that such magic is indeed possible, using the new Canvas functionality in some browsers.
This page shows how to do it using browsers that support Canvas:
http://www.permadi.com/tutorial/jsCanvasGrayscale/index.html
For IE you need to use filters, there is an example of doing greyscale here:
The way I would do it is to set the src of the img to point to a server-side PHP script
eg.,
<img src="http://mysite/grayscale.php?url='...'
That script fetches the image, runs some GD code, and returns a JPG. Something like this
This jquery plugin seems to work cross browser. I haven't tested it thouroughly though.
Using HTML5 Canvas and JavaScript
ctx.drawImage(img, 0, 0, w, h);
var imgPixels = ctx.getImageData(0, 0, w, h);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
Modern browsers can now do this in CSS – on any HTML element, not just images. Combined with IE's old filter
CSS, you can get pretty good compatibility:
image.grayscale {
/* IE */
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
/* Chrome, Safari */
-webkit-filter: grayscale(1);
/* Firefox */
filter: grayscale(1);
}
OP specifies "only JavaScript" but also mentions that IE's filter
would be acceptable if it were more widely supported, which it now (effectively) is, so I believe this is the best solution in 2015. If you really must have JavaScript:
element.style.filter = 'grayscale(1)';
Sources:
i think this code will run perfect with you no need to nested loops or any additional libraries
var image = document.getElementById("image");
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width= image.width;
canvas.height= image.height;
ctx.drawImage(image,0,0);
var imageData=ctx.getImageData(0,0, image.width, image.height);
for (var i=0;i<imageData.data.length;i+=4) {
var avg = (imageData.data[i]+imageData.data[i+1]+imageData.data[i+2])/3;
imageData.data[i] = avg;
imageData.data[i+1] = avg;
imageData.data[i+2] = avg;
}
ctx.putImageData(imageData, 0, 0, 0, 0, imageData.width, imageData.height);
document.getElementById("grayscale").appendChild(canvas);
Some image filters are available in CSS and supported by all major browsers, but you can have much more options using the HTML5 Canvas and Javascript.
However, when using Canvas based image filtering, you don't need implement the filters algorithm by yourself. Just use an image processing or Canvas manipulation library.
Examples:
In the examples below I used MarvinJ.
Loading image:
image = new MarvinImage();
image.load("https://i.imgur.com/B33rKWi.png", imageLoaded);
Gray Scale:
Marvin.grayScale(image.clone(), image);
Black and White:
Marvin.blackAndWhite(image.clone(), image, 5);
Black and White 2:
Marvin.blackAndWhite(image.clone(), image, 40);
Halftone:
Marvin.halftoneErrorDiffusion(image.clone(), image);
Runnable Example:
var canvas = document.getElementById("canvas");
image = new MarvinImage();
image.load("https://i.imgur.com/B33rKWi.png", imageLoaded);
function imageLoaded(){
// GrayScale
//Marvin.grayScale(image.clone(), image);
//image.draw(canvas);
// Black and White
Marvin.blackAndWhite(image.clone(), image, 5);
image.draw(canvas);
// Black and White 2
//Marvin.blackAndWhite(image.clone(), image, 40);
//image.draw(canvas);
// Error Diffusion
//Marvin.halftoneErrorDiffusion(image.clone(), image);
//image.draw(canvas);
}
<script src="https://www.marvinj.org/releases/marvinj-0.7.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
Nowadays you can also apply filter before rendering image into canvas. Browser support data here.
const image = document.getElementById("image");
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = image.width;
canvas.height = image.height;
ctx.filter = "grayscale()";
ctx.drawImage(image, 0, 0);
I've found this (http://spyrestudios.com/html5-canvas-image-effects-black-white/) solution to work rather well outside of IE, which, as others have noted, you'll need to use filters for.
Canvas is indeed the best client-side solution to this problem, and I just wanted to point out that, for IE, you can actually use the google exCanvas project which translate canvas commands into the proprietary Microsoft XML-based vector language, VML.
A fast way to grey out the image is by swapping color channels
ctx.drawImage(gdImage, 0, 0);
let imgdata = ctx.getImageData(0, 0, w, h);
for (var i = 0; i < imgdata.data.length; i += 4) {
imgdata.data[i ] = imgdata.data[i+2];
imgdata.data[i+1] = imgdata.data[i];
}
ctx.putImageData(imgdata, 0, 0);