大家好,今天来为大家解答
将颜色反转为灰度
这个问题的一些问题点,包括也一样很多人还不知道,因此呢,今天就来为大家分析分析,现在让我们一起来看看吧!如果解决了您的问题,还望您关注下本站哦,谢谢~- 如何区分图片的类型(可文件后缀名);
- 如何获取图片的尺寸(可右键查看图片信息);
- 如何预览本地图片(非图片阅读器);
- 如何实现图片压缩(非图片压缩工具);
- 如何操作位图像素数据(非 PS 等图片处理软件);
- 如何实现图片隐写(非肉眼可见)。
十个图片处理 「“小帮手”」 已经已经迫不及待想与你见面,还在犹豫什么?赶紧出发吧!
目录
推荐10个常用的图片处理小帮手(上)「值得收藏」
推荐10个常用的图片处理小帮手(下)「值得收藏」 本篇
2.10 Sharp
High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images. Uses the libvips library.
https://github.com/lovell/sharp
Sharp 的典型应用场景是将常见格式的大图像转换为尺寸较小,对网络友好的 JPEG,PNG 和 WebP 格式的图像。由于其内部使用 libvips ,使得调整图像大小通常比使用 ImageMagick 和 GraphicsMagick 设置快 4-5 倍 。除了支持调整图像大小之外,Sharp 还支持旋转、提取、合成和伽马校正等功能。
Sharp 支持读取 JPEG,PNG,WebP,TIFF,GIF 和 SVG 图像。输出图像可以是 JPEG,PNG,WebP 和 TIFF 格式,也可以是未压缩的原始像素数据。
「使用示例」
//改变图像尺寸sharp(inputBuffer).resize(320,240).toFile('output.webp',(err,info)=>{...});//旋转输入图像并改变图片尺寸sharp('input.jpg').rotate().resize(200).toBuffer().then(data=>{...}).catch(err=>{...});「在线示例」
https://segmentfault.com/a/1190000012903787
3.1 如何区分图片的类型
「计算机并不是通过图片的后缀名来区分不同的图片类型,而是通过 “魔数”(Magic Number)来区分。」 对于某一些类型的文件,起始的几个字节内容都是固定的,根据这几个字节的内容就可以判断文件的类型。
常见图片类型对应的模数如下表所示:
文件类型文件后缀魔数JPEGjpg/jpeg0xFFD8FFPNGpng0x89504E47GIFgif0x47494638(GIF8)BMPbmp0x424D
这里我们以阿宝哥的头像(abao.png)为例,验证一下该图片的类型是否正确:
在日常开发过程中,如果遇到检测图片类型的场景,我们可以直接利用一些现成的第三方库。比如,你想要判断一张图片是否为 PNG 类型,这时你可以使用 is-png 这个库,它同时支持浏览器和 Node.js,使用示例如下:
「Node.js」
//npminstallread-chunkconstreadChunk=require('read-chunk');constisPng=require('is-png');constbuffer=readChunk.sync('unicorn.png',0,8);isPng(buffer);//=>true「Browser」
(async()=>{constresponse=awaitfetch('unicorn.png');constbuffer=awaitresponse.arrayBuffer();isPng(newUint8Array(buffer));//=>true})();3.2 如何获取图片的尺寸
图片的尺寸、位深度、色彩类型和压缩算法都会存储在文件的二进制数据中,我们继续以阿宝哥的头像(abao.png)为例,来了解一下实际的情况:
528(十进制) =>0x0210
560(十进制)=>0x0230
因此如果想要获取图片的尺寸,我们就需要依据不同的图片格式对图片二进制数据进行解析。幸运的是,我们不需要自己做这件事,image-size 这个 Node.js 库已经帮我们实现了获取主流图片类型文件尺寸的功能:
「同步方式」
varsizeOf=require('image-size');vardimensions=sizeOf('images/abao.png');console.log(dimensions.width,dimensions.height);「异步方式」
varsizeOf=require('image-size');sizeOf('images/abao.png',function(err,dimensions){console.log(dimensions.width,dimensions.height);});image-size 这个库功能还是蛮强大的,除了支持 PNG 格式之外,还支持 BMP、GIF、ICO、JPEG、SVG 和 WebP 等格式。
3.3 如何预览本地图片
利用 HTML FileReader API,我们也可以方便的实现图片本地预览功能,具体代码如下:
在完成本地图片预览之后,可以直接把图片对应的 Data URLs 数据提交到服务器。针对这种情形,服务端需要做一些相关处理,才能正常保存上传的图片,这里以 Express 为例,具体处理代码如下:
constapp=require('express')();app.post('/upload',function(req,res){letimgData=req.body.imgData;//获取POST请求中的base64图片数据letbase64Data=imgData.replace(/^data:image\/\w+;base64,/,"");letdataBuffer=Buffer.from(base64Data,'base64');fs.writeFile("image.png",dataBuffer,function(err){if(err){res.send(err);}else{res.send("图片上传成功!");}});});3.4 如何实现图片压缩
在一些场合中,我们希望在上传本地图片时,先对图片进行一定的压缩,然后再提交到服务器,从而减少传输的数据量。在前端要实现图片压缩,我们可以利用 Canvas 对象提供的 toDataURL() 方法,该方法接收 type 和 encoderOptions 两个可选参数。
其中 type 表示图片格式,默认为 image/png。而 encoderOptions用于表示图片的质量,在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92,其他参数会被忽略。
下面我们来看一下具体如何实现图片压缩:
functioncompress(base64,quality,mimeType){letcanvas=document.createElement("canvas");letimg=document.createElement("img");img.crossOrigin="anonymous";returnnewPromise((resolve,reject)=>{img.src=base64;img.onload=()=>{lettargetWidth,targetHeight;if(img.width>MAX_WIDTH){targetWidth=MAX_WIDTH;targetHeight=(img.height*MAX_WIDTH)/img.width;}else{targetWidth=img.width;targetHeight=img.height;}canvas.width=targetWidth;canvas.height=targetHeight;letctx=canvas.getContext("2d");ctx.clearRect(0,0,targetWidth,targetHeight);//清除画布ctx.drawImage(img,0,0,canvas.width,canvas.height);letimageData=canvas.toDataURL(mimeType,quality/100);resolve(imageData);};});}对于返回的 Data URL 格式的图片数据,为了进一步减少传输的数据量,我们可以把它转换为 Blob 对象:
functiondataUrlToBlob(base64,mimeType){letbytes=window.atob(base64.split(",")[1]);letab=newArrayBuffer(bytes.length);letia=newUint8Array(ab);for(leti=0;i3.5 如何操作位图像素数据
如果想要操作图片像素数据,我们可以利用 CanvasRenderingContext2D 提供的 getImageData 来获取图片像素数据,其中 getImageData() 返回一个 ImageData 对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示,起始点为(sx, sy)、宽为 sw、高为 sh。其中 getImageData方法的语法如下:
ctx.getImageData(sx,sy,sw,sh);相应的参数说明如下:
- sx:将要被提取的图像数据矩形区域的左上角 x 坐标。
- sy:将要被提取的图像数据矩形区域的左上角 y 坐标。
- sw:将要被提取的图像数据矩形区域的宽度。
- sh:将要被提取的图像数据矩形区域的高度。
在获取到图片的像素数据之后,我们就可以对获取的像素数据进行处理,比如进行灰度化或反色处理。当完成处理后,若要在页面上显示处理效果,则我们需要利用 CanvasRenderingContext2D 提供的另一个 API —— putImageData。
该 API 是 Canvas 2D API 将数据从已有的 ImageData 对象绘制到位图的方法。如果提供了一个绘制过的矩形,则只绘制该矩形的像素。此方法不受画布转换矩阵的影响。putImageData 方法的语法如下:
voidctx.putImageData(imagedata,dx,dy);voidctx.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight);相应的参数说明如下:
- imageData: ImageData ,包含像素值的数组对象。
- dx:源图像数据在目标画布中的位置偏移量(x 轴方向的偏移量)。
- dy:源图像数据在目标画布中的位置偏移量(y 轴方向的偏移量)。
- dirtyX(可选):在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(x 坐标)。
- dirtyY(可选):在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(y 坐标)。
- dirtyWidth(可选):在源图像数据中,矩形区域的宽度。默认是图像数据的宽度。
- dirtyHeight(可选):在源图像数据中,矩形区域的高度。默认是图像数据的高度。
介绍完相关的 API,下面我们来举一个实际例子: