用 React + Rust(WebAssembly 模块)开发的简易图像处理 WebApp - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
edwardwo
V2EX    分享创造

用 React + Rust(WebAssembly 模块)开发的简易图像处理 WebApp

  •  1
     
  •   edwardwo 2019-04-24 10:49:18 +08:00 4994 次点击
    这是一个创建于 2408 天前的主题,其中的信息可能已经有所发展或是发生改变。

    入口

    简介

    去年底开始学的 Rust, 直到今年春节后, 感觉入了点门, 就想做点啥练练手, 由于一直对图像处理很感兴趣, 且此类应用比较能发挥出 WebAssembly 的特性, 于是折腾一番, 就有了这个 App. 本想等到功能稍微多些, 到了勉强可日常使用的程度再发布, 没想到实际开发中, 难度和工作量远超我的预期, 只能先发布再说.

    注: 貌似移动端暂时都不支持 WebAssembly, 因此你只能用桌面 Chrome/Firefox 打开.

    基本功能:

    • Transform: 其实也就裁剪, 旋转(暂时只支持 ±90 度), 水平 /垂直镜像, 缩小
    • Color: 彩色转黑白, Hue, Saturation, Intensity 的调整, 对比度 /亮度的调整
    • Filter
      • 像素化(俗称的马赛克效果)
      • 高斯模糊
      • 柔滑: 我提供了 2 个有雀斑的明星照片, 比较能体现出该功能的效果
      • 微缩模型化: 就是使照片主体看上去像微缩后的模型一样, 我也提供了 2 张俯视的照片体现其效果. 但该功能做的还有些缺陷, 和 PhotoShop 做的效果有一定差距

    某些功能, 如”柔滑”, 其底层的 Bilateral Filter 算法, 我暂时没精力和时间优化, 用的是最粗暴的实现法, 因此执行效率很低, 需要 10 秒以上, 它有 2 个参数: 迭代次数(每次柔滑的结果作为下次的输入), 柔滑半径, 当这 2 个参数值设的较大时, 会产生卡通效果, 如下图所示: cartoonish Gal Gadot

    但执行时间会变态到 1, 2 分钟(图片越大, 时间越长, 尽量不要载入长 /宽超过 1000px 的图片), 且执行期间, 你无法关闭该页面.

    待编辑的图片除了从电脑本地载入, 也可以读取你的摄像头(有小窗口弹出, 需要你同意). 由于所有的操作都在本地执行(没有一行服务端代码), 因此你的自拍照不会被上传. 我在摄像头返回的 video 上也添加了些有趣的滤镜效果.

    其实有些功能直接在 Javascript 中也可以高效实现, 如: 水平镜像只需 canvasContext.scale(-1, 1), 但出于学习目的, 我还是硬生生直接在 Rust 中实现了.

    由于我不太擅长 UI/交互的设计, 虽然界面看上去还行, 其实是完全照抄国外的某在线图片编辑工具befunky.

    商业化运营

    现在提这个话题, 为时过早, 而且开发初期, 我只是出于练手的目的, 但在开发过程中不时的冒出些想法, 于是就想后续完善它, 从而做成完整的 App. 以下是我的一些想法:

    一提到图片编辑, 大部分人想到的就是 PhotoShop, 但这货太专业 /臃肿 /昂贵, 普通用户压根不会用, 也用不起. 但图片编辑的需求却一直存在. 美颜相机类的 App 只是满足了一个刚需. 但还有许多其他的, 如: 风景照中需要把背景中的闲杂人员抠掉, 如: 同一款衣服有不同的颜色, 作为商家, 你不想为模特拍摄多张, 可以在 App 中调整颜色, 生成多款.

    因此, 我把 App 在功能上分 3 大块:

    • 基础的图像编辑, 大部分功能只需设置参数, 即可生效.
    • 表情包制作, 提供大量素材 /模板, 也可以读取 mp4, 配上文字, 最终生成 gif.
    • 恶搞类, 如: 把你的脸变成某明星(有过场动画), 丑化(加上刀疤, 大龅牙, 络腮胡), 性别互换, 多人合影时的换脸术, 等.

    以上这些想法, 虽然谈不上是刚需, 但很有趣, 只要有人喜欢, 有人用, App 就有价值. 技术上我有把握实现, 但工作量和难度都很大. 如果你认同我的这些想法, 或者有更好的, 并有意一起开发, 请和我联系.

    求职

    最后, 顺便求个职(有理想, 有梦想, 也要先有饭吃). 本人(座标: 上海)前后端全干, 后端(Go, NodeJS, Python, Rust)只要不是高并发, 分布式那种高端活, 都能胜任, F*ck 996.

    联系方式: ZWR3YXJkLndvODIzQGdtYWlsLmNvbQ==

    4 条回复    2019-04-24 13:14:32 +08:00
    ffeii
        1
    ffeii  
       2019-04-24 10:57:07 +08:00 via iPhone
    ios safari 可以打开
    but0n
        2
    but0n  
       2019-04-24 11:04:11 +08:00 via iPhone
    filter 是用 shader 做的吗?
    edwardwo
        3
    edwardwo  
    OP
       2019-04-24 11:19:22 +08:00
    @ffeii 移动端能打开, 是因为图片是放在<canvas />上展示的, 这个主流浏览器都支持, 但图片的编辑是调用 WebAssembly 模块实现的, 这个移动端都不支持, 因此所有操作, 点击后没反应, 也不会报错.

    @but0n 打开摄像头后的 filter 效果是通过 CSS 实现, 你看这行代码就知道了
    https://github.com/edwardwohaijun/image-editor/blob/master/www/src/components/Header/Selfie.js#L6

    图片的 filter, 如正文中提到的高斯模糊, 柔滑, 这些都是直接在 WebAssembly 中读取<canvas />上的像素值(以数组形式), 然后依次对每个像素执行 2D convolution, 做图像处理的朋友, 都知道这个概念.
    but0n
        4
    but0n  
       2019-04-24 13:14:32 +08:00 via iPhone
    哦,filter 如果用 webgl 会比 2D canvas 快一些,前者是 gpu 逐片元并行计算的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3494 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 21ms UTC 00:45 PVG 08:45 LAX 16:45 JFK 19:45
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86