When learning about HTML canvas, I found this
Example: Dynamically change images
Basically dynamically change image from colors to gray-scale and vice versa using HTML Canvas. This example select img
elements by class names ('grayscale'
) so to be able to apply this process to multiple images at once.
HTML
<img class="grayscale" src="myPicture.png" alt="Description of my picture" />
JavaScript
window.addEventListener('load', removeColors);
function showColorImg() {
this.style.display = 'none';
this.nextSibling.style.display = 'inline';
}
function showGrayImg() {
this.previousSibling.style.display = 'inline';
this.style.display = 'none';
}
function removeColors() {
var aImages = document.getElementsByClassName('grayscale'),
nImgsLen = aImages.length,
oCanvas = document.createElement('canvas'),
oCtx = oCanvas.getContext('2d');
for (var nWidth, nHeight, oImgData, oGrayImg, nPixel, aPix, nPixLen, nImgId = 0; nImgId < nImgsLen; nImgId++) {
oColorImg = aImages[nImgId];
nWidth = oColorImg.offsetWidth;
nHeight = oColorImg.offsetHeight;
oCanvas.width = nWidth;
oCanvas.height = nHeight;
oCtx.drawImage(oColorImg, 0, 0);
oImgData = oCtx.getImageData(0, 0, nWidth, nHeight);
aPix = oImgData.data;
nPixLen = aPix.length;
for (nPixel = 0; nPixel < nPixLen; nPixel += 4) {
aPix[nPixel + 2] = aPix[nPixel + 1] = aPix[nPixel] = (aPix[nPixel] + aPix[nPixel + 1] + aPix[nPixel + 2]) / 3;
}
oCtx.putImageData(oImgData, 0, 0);
oGrayImg = new Image();
oGrayImg.src = oCanvas.toDataURL();
oGrayImg.onmouseover = showColorImg;
oColorImg.onmouseout = showGrayImg;
oCtx.clearRect(0, 0, nWidth, nHeight);
oColorImg.style.display = "none";
oColorImg.parentNode.insertBefore(oGrayImg, oColorImg);
}
}
So far so good, the example works well except that when I use a big image, it makes the horizontal scroll bar appears (image width is 2400px) so I've opted to precise the width of the image in the img tag as in here:
<img class="grayscale" src="mypic3.jpg" width="698px" alt="Description of my picture" />
So that also works for the original colorful image, but for the modified one (gray-scale one) it seems to map only a portion of the image to the designed width. so instead of getting this image:
I'm getting only this one :
Notice that this happens even if oCanvas.width = nWidth;
initialize canvas width with the offset of the img tag (that is 689)
Other useless things that I've tried :
oCtx.drawImage(oColorImg, 0, 0);
oCanvas.style.backgroundSize="70%";
oCanvas.style.width="689px";
oCtx.putImageData(oImgData, 0, 0, 0, 0, 698, 410);
I appreciate any help
Edit: for the marks as duplicate
- For the one who marked the question as duplicate of question answered by just setting the canvas width, I specifically declared that it didn't work and the code above include setting canvas width.
- For the last four ones, which use the extended form of drawimage(), I did try it but it didn't work unless I set an explicit global CSS rule setting the img tag width. So I'm not sure what is the mechanics behind that. But in this case, if I don't put this rule the problem persist. So in my humble opinion, adding this particular information my help people stuck in a similar problem. as well as any explanation on why or how this works. thanks