前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Canvas 进阶(五)实现图片滤镜效果

Canvas 进阶(五)实现图片滤镜效果

作者头像
小皮咖
发布2020-01-03 09:41:17
3.1K0
发布2020-01-03 09:41:17
举报
文章被收录于专栏:小皮咖

背景

之前看过一篇写关于图片滤镜的文章,蛮有兴趣,因此作出了这个小 DEMO,可以切换多种图片滤镜并提供图片下载功能。

话不多说,先上 demogithub地址.

实现

  • 使用工具:vue iview canvas
  • 实现功能:图片绘制,滤镜修改,图片下载
  • 关键点:ctx.getImageData() ctx.putImageData() ctx.drawImage() 滤镜逻辑

1. 引入 iviewvue

代码语言:javascript
复制
<link rel="stylesheet" type="text/css" href="https://unpkg.com/view-design/dist/styles/iview.css" />
<script type="text/javascript" src="https://vuejs.org/js/vue.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/view-design/dist/iview.min.js"></script>

2. 设计整体静态页面

首先页面须有两个 canvas 标签,一个绘制原始图片,一个绘制添加滤镜效果的图片。当然还有图片上传下载按钮,以及滤镜选择框,具体如下:

代码语言:javascript
复制
 <div class="text-center">
    <div>
        <i-select
            v-model="pictureMode"
            style="width:200px"
            placeholder="请选择图像模式"
            @on-change="selectMode"
        >
            <i-option v-for="item in selectList" :value="item.value" :key="item.value"
                >{{ item.label }}</i-option
            >
        </i-select>
    </div>
    <div style="margin: 24px 0">
        <i-button icon="ios-cloud-upload-outline" type="primary" @click="$refs.input.click()"
            >上传图片</i-button
        >
        <i-button icon="ios-cloud-download-outline" type="primary" @click="downloadImage"
            >下载图片</i-button
        >
        <input type="file" ref="input" @change="uploadImage" style="display: none;" />
    </div>
    <div>
        <!-- 用户原始图片 -->
        <canvas id="origin" :width="width" :height="height" v-show="image"></canvas>
        <!-- 目标图片 -->
        <canvas id="new" :width="width" :height="height" v-show="image"></canvas>
    </div>
</div>

3. 选择图片并绘制

通过 input 标签获取选择的 file 文件,将其转化为 base64 字符串后赋值给 imagesrc 属性,待图片加载完成后在两个 canvas 中进行绘制,此为原始图片。

代码语言:javascript
复制
methods: {
    // 上传图片
    uploadImage(e) {
        var that = this;
        var file = e.target.files[0];
        if (typeof FileReader === 'undefined') {
            alert('您的浏览器不支持图片上传,请升级您的浏览器');
            return false;
        }
        var image = new Image(); // 创建图片
        image.crossOrigin = 'Anonymous'; // 解决一些跨域问题
        image.onload = function() {
            that.width = image.width; // 设置canvas的宽
            that.height = image.height; // 设置canvas的高
            that.image = image;
            // 等待canvas的宽高属性渲染完毕绘制canvas
            that.$nextTick(() => { 
                that.drawOriginImage(image);
            })
        };
        let reader = new FileReader();
        reader.readAsDataURL(file); // 生成base64
        reader.onload = e => {
            image.src = e.target.result;
        };
    },
    // 画出原始图像
    drawOriginImage(image) {
        var canvasOrigin = document.getElementById('origin');
        var ctxOrigin = canvasOrigin.getContext('2d');
        var canvasNew = document.getElementById('new');
        var ctxNew = canvasNew.getContext('2d');
        ctxOrigin.drawImage(image, 0, 0, image.width, image.height);
        ctxNew.drawImage(image, 0, 0, image.width, image.height);
    },
}

4. 选择滤镜并绘制新图片

canvas 中的 ctx 对象提供了一个方法 getImageData(), 该方法可返回某个区域内每个像素点的数值的组成的数组(例如:ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] }),data 数组中 4 个元素表示一个像素点的 rgba 值。通过对此数组每四个元素值的修改,然后重新绘制成新的 canvas,即得到我们的目标图片.

代码语言:javascript
复制
// 画出目标图像
drawImage() {
    var canvasOrigin = document.getElementById('origin');
    var ctxOrigin = canvasOrigin.getContext('2d');
    var canvasNew = document.getElementById('new');
    var ctxNew = canvasNew.getContext('2d'); 
    var imageData = ctxOrigin.getImageData(0, 0, this.width, this.height);
    var data = imageData.data; // 获取原始图像每一个像素
    this.chooseFilter(data, canvasNew, imageData); // 根据选择的滤镜处理数组
    ctxNew.putImageData(imageData, 0, 0); // 将处理的原图像的数据绘制到新图像的 canvas 中
}

5. 下载图片

通过对新的 canvas 调用 toDataURL() 返回一个包含图片展示的 data URI, 将其赋值的新的图片的 src 属性并触发点击下载事件实现下载图片功能

代码语言:javascript
复制
// 下载图片
downloadImage(image, name) {
    if (!this.image) {
        this.$Modal.error({
            title: '错误',
            content: '请上传图片先啦!!',
        });
        return;
    }
    var image = new Image();
    var canvas = document.getElementById('new');
    image.src = canvas.toDataURL();
    this.downLoad(image, 'suporka-image-filter.jpg');
},
// 下载
downLoad(image, name) {
    const dataURL = image.src;
    const link = document.createElement('a');
    link.download = name;
    link.href = dataURL;
    link.dispatchEvent(new MouseEvent('click'));
}

图像滤镜

this.chooseFilter(data, canvasNew, imageData); 是根据不同滤镜进行图片处理。这里简单介绍几种图像滤镜:

灰度滤镜

将颜色的RGB设置为相同的值即可使得图片为灰色,一般处理方法有:

1、取三种颜色的平均值

2、取三种颜色的最大值(最小值)

3、加权平均值:0.3R + 0.59G + 0.11*B

本文用的是第一种方法

代码语言:javascript
复制
for(var i = 0; i < data.length; i+=4) {
     var grey = (data[i] + data[i+1] + data[i+2]) / 3;
     data[i] = data[i+1] = data[i+2] = grey;
}

黑白滤镜

顾名思义,就是图片的颜色只有黑色和白色,可以计算rgb的平均值arg,arg>=100,r=g=b=255,否则均为0

代码语言:javascript
复制
for(var i = 0; i < data.length; i += 4) {
     var avg = (data[i] + data[i+1] + data[i+2]) / 3;
     data[i] = data[i+1] = data[i+2] = avg >= 100 ? 255 : 0;
}
复制代码

反向滤镜

取 RGB 三种颜色分别取 255 的差值。

代码语言:javascript
复制
for(var i = 0; i < data.length; i+= 4) {
      data[i] = 255 - data[i];
      data[i + 1] = 255 - data[i + 1];
      data[i + 2] = 255 - data[i + 2];

去色滤镜

rgb三种颜色取三种颜色的最值的平均值。

代码语言:javascript
复制
for(var i = 0; i < data.length; i++) {
   var avg = Math.floor((Math.min(data[i], data[i+1], data[i+2]) + Math.max(data[i], data[i+1], data[i+2])) / 2 );
   data[i] = data[i+1] = data[i+2] = avg;
}

单色滤镜

只保留一种颜色,其他颜色设为0

代码语言:javascript
复制
for(var i = 0; i < canvas.height * canvas.width; i++) {
    data[i*4 + 2] = 0;
    data[i*4 + 1] = 0;

牛顿说: “我只是站在了巨人的肩膀上”。

总结

本案例主要是对 canvasctx.getImageData,ctx.putImageData()'; 及图片数据处理的运用实现我们想要的效果。后续还有 canvas 系列的相关文章,敬请期待!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年12月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实现
    • 1. 引入 iview 与 vue
      • 2. 设计整体静态页面
        • 3. 选择图片并绘制
          • 4. 选择滤镜并绘制新图片
            • 5. 下载图片
            • 图像滤镜
              • 灰度滤镜
                • 黑白滤镜
                  • 反向滤镜
                    • 去色滤镜
                      • 单色滤镜
                      • 总结
                      相关产品与服务
                      图片处理
                      图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档