1、19基本图像效果修改像素的颜色值并不意味着必须从零开始创建整个图像,已经存在的图像也是可以修改的。有一个例子就是基本照片处理通过修改图像中的像素来修改它的显示效果。这种效果在画布中实现是很简单的,特别是现在你已经掌握了像素的操作方法。反转颜色这个效果将反转图像的颜色值,这会使它看起来有些奇怪(找不到更适合的词来形容)。基本方法就是用255减去像素现在的颜色值(150),所得的就是反转后的颜色(255-150=105)。让我们尝试一些不同的操作,然后看看最后的代码,这里并没有新知识。var image = new Image(); image.src = example.jpg; $(image
2、).load(function() context.drawImage(image, 0, 0, 1024, 683, 0, 0, 500, 500); var imageData = context.getImageData(0, 0, canvas.width(), canvas.height(); var pixels = imageData.data; var numPixels = pixels.length; context.clearRect(0, 0, canvas.width(), canvas.height(); for (var i = 0; i numPixels; i
3、+) pixelsi*4 = 255-pixelsi*4; / Red pixelsi*4+1 = 255-pixelsi*4+1; / Green pixelsi*4+2 = 255-pixelsi*4+2; / Blue ; context.putImageData(imageData, 0, 0); );前面几行代码创建了一个新的Image对象,然后加载上一节使用的示例图像。等到图像加载完成之后,将图像绘制到画布上,并将包含所有像素的ImageData对象保存到一个变量中。在保存了像素之后,清除画布,开始循环处理原始图像中所有的像素。在循环中,我们使用与上一节中第一个例子(红色正方形)相
4、同的方法来防问像素,并用255减去当前值。不需要对阿尔法值进行任何处理,因为我们要保留原始图像中的这个值。最后是将像素绘制回画布,这样就得到一个反转颜色的图像(参见图1)。图1 反转图像的颜色灰度另一个有趣的效果是灰度,这也许是更有用的一种效果。将彩色图像变为灰色(有时候也称为黑白色,但是这种说法并不准确),除了访问和修改颜色值,实现代码与反转颜色例子中的代码完全相同。for (var i = 0; i numPixels; i+) var average = (pixelsi*4+pixelsi*4+1+pixelsi*4+2)/3; pixelsi*4 = average; / Red p
5、ixelsi*4+1 = average; / Green pixelsi*4+2 = average; / Blue ; 将彩色转换为灰度要求计算出现有颜色值的平均值,即将它们加在一起然后除以颜色个数。这个平均颜色将作为三种颜色(红、绿和蓝)的值。其结果是将每一种颇色转换为灰度(参见图2)。图2 将图像转换为灰度像素化你是否曾经看到过新闻或文件中人物脸孔被像素化的情况?这是一种强大的特效,它可以将图像变得不可识别,但并不真正删除整个部分。实际上重新在画布上创建会相对简单一些,只需要将图像按栅格分割,或者对每个片段的颜色取平均值,或者选取每个片段的颜色。我们将使用的代码与上一节马赛克的例子很相
6、似。var image = new Image(); image.src = example.jpg; $(image).load(function() context.drawImage(image, 0, 0, 1024, 683, 0, 0, 500, 500); var imageData = context.getImageData(0, 0, canvas.width(), canvas.height(); var pixels = imageData.data; context.clearRect(0, 0, canvas.width(), canvas.height(); va
7、r numTileRows = 20; var numTileCols = 20; var tileWidth = imageData.width/numTileCols; var tileHeight = imageData.height/numTileRows; for (var r = 0; r numTileRows; r+) for (var c = 0; c numTileCols; c+) ; ; );循环之前的代码都是一样的。访问图像,等待图像加载,将它绘制到画布中,保存ImageData对象,从画布清除该图像,然后给分割的图像赋值确定块(片段)的数量和尺寸。这两个循环的工作方
8、式与马赛克的例子是一样的:第一个循环处理每一行块,第二个循环则处理当前行中的每一个块。而新的代码位于循环中,访问颜色值和创建像素化效果。这里将使用第二种方法来获取像素化效果的颜色值,为每一个块选择一种颜色。最简单的方法是使用块的中心位置像素,将以下代码添加到第二个循环中,就可以得到这个信息:var x = (c*tileWidth)+(tileWidth/2); var y = (r*tileHeight)+(tileHeight/2); var pos = (Math.floor(y)*(imageData.width*4)+(Math.floor(x)*4); 前两行将得到当前块中心像素从
9、0开始表示的(x,y)坐标。这个计算方法与马赛克例子非常相似,先找到块边缘的(x,y)坐标位置,然后加上一半宽度或高度,从而确定中心。然后将(x,y)坐标传入标准公式,这样就得到CanvasPixelArray中该像素的索引值但你可能注意到了,(x,y)坐标值在Math对象的floor方法中进行了取整处理。其原因是,除(x,y)是整数,否则这个返回的索引将是错误的,所以我们使用floor方法将值取整为下一个最小整数(侧如,3.567取整后变成3)。最后,我们得到了访问颜色值和绘制像素化效果所需要的全部信息。将下面的代码插入到变量pos的声明语句之后。var red = pixelspos; v
10、ar green = pixelspos+1; var blue = pixelspos+2; context.fillStyle = rgb(+red+, +green+, +blue+); context.fillRect(x-(tileWidth/2), y-(tileHeight/2), tileWidth, tileHeight); 这里没有新代码,它只是访问红色、绿色和蓝色值,然后使用这些值来设置fillStyle。最后一步是在块的位置上绘制一个正方形,它是使用所访问的颜色填充的。结果是将示例图像变成一个独特的像素化效果(参见图3)。图3 使用画布实现图像像素化我们可以进一步将正方形修改为圆形(参见图4)。context.beginPath(); context.arc(x, y, tileWidth/2, 0, Math.PI*2, false); context.closePath(); context.fill();现在效果更酷了!图4 在画布中使用圆形替换正方形实现图像像素化 4 / 4