首页 > 其他分享 >前端线上图片生成马赛克

前端线上图片生成马赛克

时间:2023-01-03 18:03:15浏览次数:60  
标签:canvas 生成 端线 xhr pixeArr sampleSize let 马赛克 图片

前言

说起图片的马赛克,可能一般都是由后端实现然后传递图片到前端,但是前端也是可以通过canvas来为图片加上马赛克的,下面就通过码上掘金来进行一个简单的实现。

实现

markup

<img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d0b4e30cd0f648fcbe675992ddcb90f1~tplv-k3u1fbpfcp-watermark.image?" id="image" />

style

body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}

#image {
width: 200px;
height: auto;
margin-right: 30px;
}

script

let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let img = document.getElementById("image");
let img1 = new Image();

getBase64(document.getElementById("image").src).then((res) => {
img1.src = res;
});

img1.onload = function () {
let w = img1.width;
let h = img1.height;

canvas.width = w;
canvas.height = h;
ctx.drawImage(img1, 0, 0);

let pixeArr = ctx.getImageData(0, 0, w, h).data;
let sampleSize = 40;

for (let i = 0; i < h; i += sampleSize) {
for (let j = 0; j < h; j += sampleSize) {
let p = (j + i * w) * 4;
ctx.fillStyle =
"rgba(" +
pixeArr[p] +
"," +
pixeArr[p + 1] +
"," +
pixeArr[p + 2] +
"," +
pixeArr[p + 3] +
")";
ctx.fillRect(j, i, sampleSize, sampleSize);
}
}
// img.src = canvas.toDataURL("image/jpeg");
let img2 = new Image();
img2.src = canvas.toDataURL("image/jpeg");
img2.width = img.width;
img2.height = img.height;
document.body.appendChild(img2);
};

function getBase64(imgUrl) {
return new Promise(function (resolve, reject) {
window.URL = window.URL || window.webkitURL;
let xhr = new XMLHttpRequest();
xhr.open("get", imgUrl, true);
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status == 200) {
let blob = this.response;
let oFileReader = new FileReader();
oFileReader.onloadend = function (e) {
let base64 = e.target.result;
resolve(base64);
};
oFileReader.readAsDataURL(blob);
}
};
xhr.send();
});
}

代码运行效果

前端线上图片生成马赛克_马赛克

实现过程

思路

最开始需要实现马赛克功能是需要通过canvas提供的一个获取到图片每一个像素的方法,我们都知道,图片本质上只是由像素组成的,越清晰的图片,就有着越高的像素,而像素的本质,就只是一个个拥有颜色的小方块而已,只要把一张图片放大多倍,就能够清楚的发现。

canvas实现

通过 canvas 的 getImageData 这个方法,我们就能够拿到图像上所有像素组成的数组,并且需要生成马赛克,意味着我们需要把一个范围内的色块的颜色都改成一样的,也就是通过canvas来重绘图片,

let pixeArr = ctx.getImageData(0, 0, w, h).data;
let sampleSize = 40;

for (let i = 0; i < h; i += sampleSize) {
for (let j = 0; j < h; j += sampleSize) {
let p = (j + i * w) * 4;
ctx.fillStyle =
"rgba(" +
pixeArr[p] +
"," +
pixeArr[p + 1] +
"," +
pixeArr[p + 2] +
"," +
pixeArr[p + 3] +
")";
ctx.fillRect(j, i, sampleSize, sampleSize);
}
}
复制代码

通过双重循环来循环图片所有的色块,其中的跨度就是我们设定好的色块大小,色块调整的越大,马赛克后图片更模糊,越小,图片的模糊度就会降低。在通过 fillStyle 选取颜色,以及 fillRect 重绘 canvas 实现了将整个 canvas 的色块都进行改变,最后在导出重绘后的图片,无论是改变原来的图片地址,或者是新加一张图片作为对比,就都是可行的了。

canvas 跨域问题

在使用 getImageData 获取图片的时候,如果使用的是线上图片,浏览器会爆出跨域的错误:

前端线上图片生成马赛克_图片_02

而上文中出现问题的图片是存放在本地的或者线上的,本地的图片默认是没有域名的,线上的图片并且是跨域的,所以浏览器都认为你是跨域,导致报错。

那么对于本地图片,我们只需要将图片放到和html对应的文件夹下,子文件夹也是不可以的,就能够解决,对于线上的图片,我们可以采用先把它下载下来,再用方法来获取数据的这种方式来进行。

function getBase64(imgUrl) {
return new Promise(function (resolve, reject) {
window.URL = window.URL || window.webkitURL;
let xhr = new XMLHttpRequest();
xhr.open("get", imgUrl, true);
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status == 200) {
let blob = this.response;
let oFileReader = new FileReader();
oFileReader.onloadend = function (e) {
let base64 = e.target.result;
resolve(base64);
};
oFileReader.readAsDataURL(blob);
}
};
xhr.send();
});
}
复制代码

下载图片就不说了,通过浏览器提供的 API 或者其他封装好的请求工具都是可以的,在请求成功之后,我们将图片转化为 base64 并且返回,这样就能够获取线上图片的数据了。

总结

本文提供了一种前端生成马赛克图片的方案,并且对于线上的图片,也能够通过先异步下载图片在进行转换的策略,实现了图片添加马赛克的功能。

完整附件:​​点此下载​

标签:canvas,生成,端线,xhr,pixeArr,sampleSize,let,马赛克,图片
From: https://blog.51cto.com/u_15723831/5986228

相关文章

  • 次小生成树
    次小生成树简介:求权值和第二小的生成树的权值之和解法:我们考虑当前已经构成的一颗最小生成树,说明此时所选的所有边是满足权值和最小的,当我们枚举一条新边时,如果将其......
  • 基于Mock.js,使用C#生成模拟数据
    获取某前端框架,使用 Mock.js生成模拟数据,想要对api进行改造,并且保留原始数据,需要使用C#重写后端api的数据模拟的内容:Random.guid()uuid:'@uuid',id:'@id......
  • wpf应用程序生成类库报错库项目文件无法指定 ApplicationDefinition 元素 项目文件包
    解决方案:在程序中APP.xaml文件上右键属性将生成操作applicationdefinition改成Page即可。......
  • java 生成uuid
    /***提供通用唯一识别码(universallyuniqueidentifier)(UUID)实现**@authorruoyi*/publicfinalclassUUIDimplementsjava.io.Serializable,Comparable<UUID......
  • SAP-FI模块 如何处理自动生成会计凭证增强
    一.相关问题概览1.固定资产业务过渡科目摘要增强功能-F-02  需用表BKPF、BSEG、T001。通过BUKRS、BELNR、GJAHR三个字段相等关联BKPF与BSEG。通过BKPF-BUKRS=T00......
  • laravel生成PDF使用插件barryvdh/laravel-dompdf及中文乱码问题解决
    使用1.composer安装composerrequirebarryvdh/laravel-dompdf2.发布配置文件,生成的配置文件config/dompdf.php,也可选择忽略此步骤phpartisanvendor:publish......
  • html2canvas页面生成截图
    什么是html2canvs?html2canvas 的作用就是允许让我们直接在用户浏览器上拍摄网页或其部分的“截图”。它的屏幕截图是基于 DOM 的,因此可能不会100%精确到真实的表......
  • ef 根据数据库生成实体
    1.安装Microsoft.EntityFrameworkCore.Tools6.0.12版本 高版本可能不兼容2.安装Pomelo.EntityFrameworkCore.MySqlmysql 6.0.2(mysql)3.安装Microsoft.EntityFramew......
  • .NET6 图片上传后生成缩略图
    1、通过NuGet包管理器安装SkiaSharp///<summary>///创建图像的缩略图。使用SkiaSharp,以支持跨平台。///</summary>///<paramname="orgPath......
  • python随机生成字符串
    importrandomdefgenerate_code(code_len=4):all_charts='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'last_pos=len(all_charts)......