JavaScript中的图像处理与合成(一)简介:图像处理现在已经成为我们生活中的刚需,想必每个人都经常有这种需求。在实际的前端业务中,往往有很多项目需要进行图像处理和处理。过去一段时间因公司业务需要,积累了一些这方面的干货,会在年后的时间里总结成系列文章分享给大家,希望能给大家带来启发和帮助致前端童鞋们辛苦了~~~?本系列分为以下四个部分:图像处理基础技术的缩放与裁剪;图像合成基本图像处理技术;基本图像处理技术的文本合成;算法图像处理技术;看到很多坑或者是在实战中遇到的经验,应该算是干货满满了~~如果能够通读的话,应该能够大大提升你对前端图像处理领域的理解。有兴趣的童鞋可以和我深入探讨。希望这篇文章能够达到抛砖引玉的效果,让前端在图像处理上有更多的可能。不足之处还请见谅。通过这些积累,我封装了几个项目中常用的功能:图片合成:ExampleGit图片裁剪:ExampleGit人像抠图:ExampleGit唠叨完这些老套路,我们就开始起飞了!~~??????首先我把前端图像处理暂且分为两种:基本型和算法型;基本类型的图像处理技术:图像缩放、旋转、加边框、图像合成、拼图等服务都是基本类型图像处理的区别在于不需要使用像素级算法,而是通过计算对图像进行变换并改变图像的大小和位置。比如常用的贴纸函数:算法型图像处理:这类图像处理比较复杂,其特点是通过像素级算法将图像的像素点通过RGBA通道值进行变换。比如我们用photshop或者美图秀秀工具对图片进行美化/滤镜/黑白/抠图/模糊等操作,这一类的重点主要在算法和性能层面。比如常用的彩妆功能:本系列从基本的妆容类型开始我们的旅程。图像处理的基本类型在实际项目中有大量的使用场景。主要是利用canvas的能力完成的。不存在性能和兼容性问题,可以满足在线运行标准。这里我将图像处理的基本类型大致分为以下几种,基本可以涵盖所有日常业务场景:图像缩放;裁剪图像;图像合成;图像和图像的合成,例如贴纸、边框、水印等;给图片添加文字;为图片添加基本几何图形;Tips:我已经将此类图片处理场景封装成一个插件,基本可以满足此类图片处理的所有需求,git地址(欢迎讨论);在介绍具体功能之前,由于图片的绘制完全依赖于图片的加载,我们先了解一些前置知识。1.跨域图片首先加载和绘制图片涉及到图片的跨域问题,所以如果是在线图片,需要在图片服务器上设置一个跨域的header,并在之前设置标签前端加载图片crossOrigin设置为*,否则绘制到canvas时会报跨域错误。Tips:这里积累了一些坑,分享给大家:1.crossOrigin需要严格设置,即只有在线图片的时候才可以设置,在线图片的时候一定不能设置本地路径或base64,否则在某些系统中2.当项目是本地包环境时,比如构建成App时,crossOrigin值无效,webview的安全机制会导致跨域错误无论是否设置该值都会被报告。解决方法是:所有图片都需要转成base64才能正确绘制;3、crossOrigin值必须在图片加载前设置,即在将src赋值给
之前设置,否则无效;2.图片的加载是由于canvas的绘制需要的是已经加载好的图片。我们需要保证绘制的素材图片已经加载,所以需要使用
的onload事件,可以使用html中已有的图片,也可以用js创建图片对象:functionloadImage(image,loader,error){//创建一个图像对象来加载图像;让img=newImage();//当是在线图片时,需要设置crossOrigin属性;if(image.indexOf('http')==0)img.crossOrigin='*';img.onload=()=>{加载(img);//使用后清空对象,释放内存;setTimeout(()=>{img=null;},1000);};img.onerror=()=>{error('img加载错误');};img.src=image;}介绍完图片加载的前置知识,我们先来看最简单的图片处理---缩放裁剪!Tips:相信看到这篇文章的你,如果对canvas还不是很了解,可以去查阅相应的API文档。本文不会详细讲解canvas的基本API。1.图像缩放图像缩放最常见的场景是图像压缩。在保证图片清晰的前提下,通过合理缩小图片尺寸,可以大大缩小图片尺寸。在实际应用场景中,它有着广泛的用途。例如,在上传图片时,用户上传的图片可能尺寸非常大。例如,手机拍摄的照片尺寸往往可以达到1920*2560,尺寸可能超过5M。在项目中,我们可能不需要使用这么大的尺寸。这时候图片压缩可以大大优化加载速度,节省带宽;1.新建画布,设置宽高为需要压缩的尺寸;画布为图片缩放后的尺寸。这里有一点需要保持图片的比例不变,所以需要计算canvas的宽高:letimgRatio=img.naturalWidth/img.naturalHeight;//创建一个canvas容器;letcvs=document.createElement('canvas');//获取容器中的画板;让ctx=cvs.getContext('2d');cvs.width=1000;cvs.height=cvs.width/imgRatio;2.绘制图像,然后导出为base64;这里介绍两个最常用的方法:ctx.drawImage(image,dx,dy,dw,dh):这个方法实际上最多可以接收9个参数,实现压缩只需要用到其中的5个参数,以及其余参数将在其他部分使用时详细说明;image:要绘制的图片源,需要接收加载的HTMLImageElement、HTMLCanvasElement或HTMLVideoElement;dx/dy:相对于画布左上角绘图起点的坐标;dw/dh:绘图的宽高,不锁定纵横比,图像可以变形;cvs.toDataURL(type,quality):该方法用于将画布上的内容以base64格式导出图片,可以配置2个参数;type:图片格式,一般可以使用image/png或image/jpeg,当图片不包含透明度时,推荐使用jpeg,可以大大减小导出图片的尺寸;quality:图像质量,可以使用0到1之间的任意值;经过测试,将该值设置为0.9比较合适,可以有效减小图片文件的大小,基本不影响图片的清晰度。导出的base64压缩后的最终图片;Tips:这里有个坑,如果要导出jpg格式的图片,必须用image/jpeg,不能用image/jpg;//在缩放后的画布上等比例绘制原始图像;ctx.drawImage(image,0,0,cvs.width,cvs.height);//将绘制的图片导出为base64格式;让b64=cvs.toDataURL('image/jpeg',0.9);3.将多种格式的图片转成base64;我们使用原生图片上传功能
