缩放旋转滤镜篇
因为有跨域请求的问题,双击打开会出问题,请不要双击打开文件。代码地址如下:
https://github.com/YDJSIR-NJU/NJUSE-21-Frontend/tree/main/OnlinePS
实现功能
本代码实现了以下所有功能。
滤镜功能,可以选择一组预设滤镜;
手动更改属性(例如亮度,对比度,饱和度)以获得所需的结果;
裁剪、旋转和缩放图像;
图像风格迁移;
代码说明
本项目全部使用了本地缓存的CSS
和JavaScript
,没有使用Node.js
或CDN
。
直接双击打开index.html
会有跨域问题。请保证访问时网页放在一个HTTP服务器中。我采用的是nginx-1.16.1
。
选项区左上角可以上传待修改的图片或下载画布的内容(格式为png
)。
滤镜与图像风格迁移
本项目使用的是Lena.js
。仓库地址:https://github.com/davidsonfellipe/lena.js
左侧的是三种滤镜,红色,灰度与反色,而右侧是三种图像风格。代码调用部分十分简单,举一个例子。
1 | fliter1.addEventListener("click", (event) => { |
这一栏会在旋转与裁剪模式下被隐藏。
手动更改属性
本项目使用的是caman.js
。仓库地址:https://github.com/fengyuanchen/cropperjs
点击对应的按钮会触发对应的效果,可以调整亮度、对比度、饱和度和曝光度。
代码调用部分也十分简单,举一个例子。
1 | lightUp.addEventListener("click", (event) => { |
裁剪、旋转与缩放图像
在非旋转与裁剪模式下,缩放通过第一行中间的按钮进行。在旋转与裁剪下,这两个按钮不可用。
裁剪、旋转与缩放图像功能在旋转与裁剪模式下可用。点击左下角旋转与裁剪
进入该模式。
本项目使用的是copper.js
。仓库地址:https://github.com/meltingice/CamanJS
使用鼠标滚轮可以缩放图片。进入时默认是拖拽裁切模式(选定选区),光标呈十字。双击非选区可以将模式切换为移动模式,即选区对屏幕不动,图片移动(无论是否有选区)。选区的边缘可以随意调整。
点击放弃选区
,可以取消选区并不做任何更改。点击裁剪选区
会裁剪出对应区域。如果操作结束,点击右下角确认并退出
可以返回一般模式(有选区的情况下必须放弃选区或者裁剪选区才能退出)。点击左转90°
和右转90°
可以旋转图片。
详情请见代码部分。
水印篇
因为有跨域请求的问题,双击打开会出问题,请不要双击打开文件。代码地址如下:
https://github.com/YDJSIR-NJU/NJUSE-21-Frontend/tree/main/Watermark
使用说明
本次代码且没有采用第三方库,网站可以在
Chrome 91
、Firefox 91
和新Edge
中正常打开;由于直接打开会有跨域请求相关问题,==请不要直接双击打开
html
文件,而是将文件置于HTTP服务器环境下用浏览器打开==。开发时使用的是nginx-1.16.1
;效果的刷新可能有一定延迟,请不要操作过快;
代码中有详细注释;
项目文件结构如下图所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/
│ detailed.html
│ icon.ico
│ README.md
│
├─css
│ common.css
│ index.css
│
├─img
│ banner.png
│
├─js
│ canvas-invisible.js
│ canvas-visible.js
│
└─README.assets
可见水印.png
不可见水印.png
查看水印.png
实现过程
本次实验中所有的水印均为YDJSIR
和当前UNIX时间戳,字体为微软雅黑,字号为16px。
可见水印
可见水印的实现过程参考了https://cloud.tencent.com/developer/article/1158636。
整体的实现流程是新建一个canvas
画布,在画布中绘制对应图片后,再在上面用canvas
绘制倾斜角度随机,颜色随机且有随机抖动角度的半透明水印矩阵。绘制完成后,把原HTML文件中的图片源换为canvas
的结果。
在展示有水印的图片时,点击该展示区域中的按钮,可以查看原图,而后按钮提示变为可见水印
,再次点击则再次生成带水印的图片。由于水印的倾斜角度是随机的,所以每一次重新添加水印水印的位置都会改变。
绘制部分核心代码如下。
1 | // 绘制水印 |
不可见水印部分的绘制代码也是类似的,只不过绘制时没有随机颜色,fillStyle = "rgba(255, 255, 255, 1)"
,下面不再赘述。
不可见水印
不可见水印的实现过程参考了http://www.alloyteam.com/2016/03/image-steganography/。
添加水印
整体的实现流程是在一个大小和对应图片相同的canvas
画布中先绘制对应水印获得其图像数据后,重置画布,绘制对应图片并获得原始图片的图像数据。同时逐个遍历两组数据中的每一个像素,将原始图片中水印中有内容的点的通道的值置为偶数,水印中没有内容的点的通道的值置为奇数。将这样的图像数据重新绘制,便可得到带有隐式数字水印的图片。下面这张图便是带有隐式水印的。原图附在压缩包中。
实现部分的核心代码如下。
1 | function encodeImg(src, id, color) { |
1 | function mergeData(ctx, color, watermarkData, originalData) { |
查看水印
想要查看水印,只需要将canvas
中的图像数据读出,选择其中特定通道为偶数的点,将该通道拉满,反之将其降为0,其他点的其他通道可以选择性关闭(当然下图是没有关闭的效果,不影响),再重新绘制,便可看到类似下方的效果。
这张图是与上面的那张图相对应的解码后的结果。原图附在压缩包中。
在有隐式水印的情况下,点击图片下方按钮可查看如下图所示的水印解码结果,再点一次则刷新为原图,再点一次则又会添加隐式水印并回到一开始的状态。
核心实现代码如下。
1 | function decodeImg(id, color) { |