利用glfx.js完成纯前端的实时图像处理

今天在工作中要解决一个前端图像处理的需求。在网上查找资料后,发现了glfx.js这样一个js图像处理库,它是一个基于WebGL的实时图像处理库。使用的方法如下:

下载glfx

glfx.js的源码下载下来,为了适应es6语法,在文件末尾最后加上一行代码

export {fx};

图像处理

封装一个Vue图像处理组件,暂且叫做FrontProcess.vue。这个组件接收父组件待处理的图像url,当进行了图像处理操作后,携带处理后的图像url给父组件发送emit事件。父组件接收到事件后,更新图像url

首先,我们导入glfx脚本

import {fx} from '@/assets/js/glfx.js'

定义data和props

data(){
	// 这里定义的是一些对象(保存canvas等数据)和参数值(如亮度/对比度等值)
    return {
        valueOfBrightness: 0,
        _canvas: null,
        _texture: null,
        imgElement: null,
        _draw: null,
        originalSrc: '',
        valueOfContrast: 0,
        isCurves: false,
        isDenoise: false,
        valueOfHue: 0,
        valueOfSaturation: 0,
        valueOfNoise: 0,
        valueOfSepia: 0,
        usmRadius: 0,
        usmStrength: 0,
        opBtn: []
    }
},
props: {
   imgUrl: {
       required: true
   }
}

将数据绑定到模板上

<div class="front-process-container" v-loading="loading">
      <img id="original" crossorigin="anonymous" :src="imgUrl" ref="originalImg">
      <div class="slider-wrap">
          <label class="slider-label">亮度</label>
          <el-slider v-model="valueOfBrightness" :max="100" :min="-100" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">对比度</label>
          <el-slider v-model="valueOfContrast" :max="100" :min="-100" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">色调</label>
          <el-slider v-model="valueOfHue" :max="100" :min="-100" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">饱和度</label>
          <el-slider v-model="valueOfSaturation" :max="100" :min="-100" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">加噪</label>
          <el-slider v-model="valueOfNoise" :max="100" :min="0" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">深褐</label>
          <el-slider v-model="valueOfSepia" :max="100" :min="0" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">锐化半径</label>
          <el-slider v-model="usmRadius" :max="200" :min="0" @change="drawByParams"></el-slider>
      </div>
      <div class="slider-wrap">
          <label class="slider-label">锐化强度</label>
          <el-slider v-model="usmStrength" :max="5" :min="0" :step="0.01" @change="drawByParams"></el-slider>
      </div>
      <el-button class="op-btn" @click="drawByParams('curves')" :class="{active: isCurves}">反显</el-button>
      <el-button class="op-btn" @click="drawByParams('denoise')" :class="{active: isDenoise}">降噪</el-button>
      <el-button class="op-btn" @click="resetImg">恢复原图</el-button>
</div>

绑定方法

// 初始化,根据glfx的说明按顺序调用,并将这些对象保存下来。
getWebGLElements() {
    if (!this._canvas) {
        this._canvas = fx.canvas();
    }

    if (!this.imgElement) {
        this.imgElement = this.$refs.originalImg;
        this.originalSrc = this.imgElement.src;
    }

    if (!this._texture) {
        this._texture = this._canvas.texture(this.imgElement);
    }

    if (!this._draw) {
        this._draw = this._canvas.draw(this._texture)
    }
}

// 处理图像
drawByParams(operation) {
    this.resetProperty()
    let opIndex = _.indexOf(this.opBtn, operation)
    if (opIndex !== -1) {
        this.opBtn.splice(opIndex, 1)
    } else {
        this.opBtn.push(operation)
    }
    this._draw.
        brightnessContrast(this.valueOfBrightness / 100, this.valueOfContrast / 100).
        hueSaturation(this.valueOfHue / 100, this.valueOfSaturation / 100).
        noise(this.valueOfNoise / 100).
        sepia(this.valueOfSepia / 100).
        unsharpMask(this.usmRadius, this.usmStrength);
    if (_.indexOf(this.opBtn, 'curves') !== -1) {
        this.isCurves = true
        this._draw.curves([[0,1], [1,0]], [[0,1], [1,0]], [[0,1], [1,0]])
    } else {
        this.isCurves = false
    }
    if (_.indexOf(this.opBtn, 'denoise') !== -1) {
        this.isDenoise = true
        this._draw.denoise(20)
    } else {
        this.isDenoise = false
    }
    this._draw.update()
    this.$emit('changeImg', this._canvas.toDataURL('image/png'))
}

图像处理效果图

这是被随意拖拽设置的参数,然后调用glfx各个filter实现的效果。glfx还提供了很多图像处理的filter,我这里只用了其中一部分用来做演示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tEpsmk9w-1571106060246)(http://wbjiang.cn/glfx%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86%E6%95%88%E6%9E%9C%E5%9B%BE.png?imageMogr2/auto-orient/blur/1x0/quality/75|watermark/2/text/d2JqaWFuZy5jbg==/font/5qW35L2T/fontsize/640/fill/IzQ5NzZEQg==/dissolve/90/gravity/SouthWest/dx/10/dy/10)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yemHc1E8-1571106060246)(http://wbjiang.cn/glfx%E6%95%88%E6%9E%9C%E5%9B%BE2.png?imageMogr2/auto-orient/blur/1x0/quality/75|watermark/2/text/d2JqaWFuZy5jbg==/font/5qW35L2T/fontsize/640/fill/IzQ5NzZEQg==/dissolve/90/gravity/SouthWest/dx/10/dy/10)]

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值