利用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)]

发布了98 篇原创文章 · 获赞 41 · 访问量 20万+
展开阅读全文

webgl在做图形处理的时候如何挡住半边

06-26

公司的一个开源VR项目,现在已经实现了360度视频播放,目前准备实现180度视频播放,webgl实在是不精通,求懂的人给看一下。 下面的代码是播放360度视频的代码, 目前要做180度的,180度视频内容是左右的, 每一帧要处理两次,每次处理要遮挡住一边, 然后webgl畸变处理另外一边。 texSubImage2D和texCopyImage2D已经试过了,能成功,但是内存拷贝太占系统资源, 我们这个是播放4K影片的,用不了。 代码如下 webGL.gl = canvas.getContext("webgl"); /* video 是加载的一个本地视频流 */ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, video); /** * Drawing the scene */ drawOneEye: function(eye) { webGL.gl.useProgram(shader.program); webGL.gl.bindBuffer(webGL.gl.ARRAY_BUFFER, positionsBuffer); webGL.gl.vertexAttribPointer(shader.attributes['aVertexPosition'], 2, webGL.gl.FLOAT, false, 0, 0); // Specify the texture to map onto the faces. webGL.gl.activeTexture(webGL.gl.TEXTURE0); webGL.gl.bindTexture(webGL.gl.TEXTURE_2D, texture); webGL.gl.uniform1i(shader.uniforms['uSampler'], 0); var projectionInverse = mat4.create(); mat4.invert(projectionInverse, eye.projectionMatrix); var inv = mat4.create(); mat4.multiply(inv, rotation, projectionInverse); webGL.gl.uniformMatrix4fv(shader.uniforms['proj_inv'], false, inv); // Draw webGL.gl.bindBuffer(webGL.gl.ELEMENT_ARRAY_BUFFER, verticesIndexBuffer); webGL.gl.drawElements(webGL.gl.TRIANGLES, 6, webGL.gl.UNSIGNED_SHORT, 0); }, 详细的代码在https://github.com/vrzome 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览