canvas马赛克
马赛克思路
像素说明
一张图片的宽高积为像素个数:像素个数 = width * height
canvas中的ImageData中的 ImageData.data 数组,包含了图片的所有像素点。而一个像素点就是一个 rgba ,就是四个元素。所以Image.data中的元素,每四个元素为一组,为一个像素点
步骤
-
第一步要把图片插入到 canvas 中
const image = new Image() image.src = '图片地址' image.onload = function(){ //onload属性适用于拥有 src 属性的元素,用来表示元素加载成功,当图片加载成功后执行匿名函数 ctx.drawImage(image,x,y,width,height) } -
读取插入的图片,返回一个 ImageData 对象,该对象中,包含了图片的像素值与宽高
const imageData = ctx.getImageData(x,y,width,height) -
将获取到的图片信息,以像素的形式,写入到 canvas 中
ctx.putImageData(imageData,x,y) -
回看像素说明,先对一个单位像素进行操作
const x = 1,y = 1 //获取一个单位像素信息 const newImageData = ctx.getImageData(x,y,imageData) //写入一个单位像素信息 ctx.putImageData(x,y,newImageData) -
设置马赛克模糊度 size,该模糊度表示,在一个 5*5 的像素范围内,他们的像素值相同,以此达到马赛克效果
const size = 5,width = 800,height=600 // 操作像素,x:表示图片x坐标位置,y:表示图片y坐标位置 function pxOperation(x, y, width, height, size, newImageData) { // 在 5*5 的范围内取一个单元像素点 const { data } = ctx.getImageData(x, y, 1, 1) // 将该像素点全部写入 size 范围内 for (let n = 0; n < size; n++) { for (let m = 0; m < size; m++) { newImageData.data[(x + n + (y + m) * width) * 4 + 1] = data[1] newImageData.data[(x + n + (y + m) * width) * 4 + 2] = data[2] newImageData.data[(x + n + (y + m) * width) * 4 + 0] = data[0] newImageData.data[(x + n + (y + m) * width) * 4 + 3] = data[3] } } } -
将马赛克效果铺满整个图片
for (let x = 0; x < w / size; x++) { for (let y = 0; y < h / size; y++) { pxOperation(x * size, y * size, w, h, size, newImageData) } } // 像素写入图片中 ctx.putImageData(newImageData, 800, 0)
案例
第一步:通过单像素复制图片
效果图:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.syt {
background-color: rgba(158, 169, 203, 255);
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="400">
您的浏览器不支持canvas,请更换浏览器
</canvas>
<script>
window.onload = () => {
if (canvas.getContext) {
canvas.style.backgroundColor = 'orange'
const ctx = canvas.getContext('2d')
const image = new Image(200, 300)
image.width = 200
image.src = '../images/2.jpg'
image.onload = () => {
draw(image)
}
function draw(image) {
const size = 20
ctx.drawImage(image, 0, 0, 400, 400)
const imageData = ctx.getImageData(0, 0, 400, 400)
const width = imageData.width
const height = imageData.height / size
setRGBA(400, 0, imageData)
}
function getRGBA(x, y) {
const imageData = ctx.getImageData(x, y, 1, 1)
return imageData.data
}
function setRGBA(x, y, imageData) {
const size = 2
const w = imageData.width
const h = imageData.height
const newImageData = ctx.createImageData(imageData)
const arr = newImageData.data
for (let i = 0; i < w; i++) { //w:代表一行有多少个像素
for (let j = 0; j < h; j++) { //h:代表有多少行
// j * w :j行 乘 每行的像素
// + i :表示当前像素点之前还有多少个像素点,
// * 4 :是因为 ImageData.data中的数据,每四个元素 为一组,组成 rgba
// (j * w + i) * 4 :代表定位到当前元素的 rgba[0]的位置
const color = getRGBA(i, j)
arr[(j * w + i) * 4] = color[0]
arr[(j * w + i) * 4 + 1] = color[1]
arr[(j * w + i) * 4 + 2] = color[2]
arr[(j * w + i) * 4 + 3] = color[3]
}
}
ctx.putImageData(newImageData, x, y)
}
}
}
</script>
</body>
</html>
第二步:间隔像素取值
效果图:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.syt {
background-color: rgba(158, 169, 203, 255);
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="400">
您的浏览器不支持canvas,请更换浏览器
</canvas>
<script>
window.onload = () => {
if (canvas.getContext) {
canvas.style.backgroundColor = 'orange'
const ctx = canvas.getContext('2d')
const image = new Image(200, 300)
image.width = 200
image.src = '../images/2.jpg'
image.onload = () => {
draw(image)
}
function draw(image) {
const size = 4
ctx.drawImage(image, 0, 0, 400, 400)
const imageData = ctx.getImageData(0, 0, 400, 400)
const newImageData = ctx.createImageData(imageData)
const width = imageData.width / size
const height = imageData.height / size
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
setRGBA(imageData, newImageData, i, j, size)
}
}
}
function getRGBA(x, y) {
return ctx.getImageData(x, y, 1, 1).data
}
function setRGBA(imageData, newImageData, x, y, size) {
const color = getRGBA(x * size, y * size)
const w = newImageData.width
const h = newImageData.height
const tempData = newImageData.data
tempData[(w * y + x) * size * 4] = color[0]
tempData[(w * y + x) * size * 4 + 1] = color[1]
tempData[(w * y + x) * size * 4 + 2] = color[2]
tempData[(w * y + x) * size * 4 + 3] = color[3]
ctx.putImageData(newImageData, 400, 0)
}
}
}
</script>
</body>
</html>
第三步:马赛克
效果图:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.syt {
background-color: rgba(158, 169, 203, 255);
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="400">
您的浏览器不支持canvas,请更换浏览器
</canvas>
<script>
window.onload = () => {
if (canvas.getContext) {
canvas.style.backgroundColor = 'orange'
const ctx = canvas.getContext('2d')
const image = new Image(200, 300)
image.width = 200
image.src = '../images/2.jpg'
image.onload = () => {
draw(image)
}
function draw(image) {
const size = 4
ctx.drawImage(image, 0, 0, 400, 400)
const imageData = ctx.getImageData(0, 0, 400, 400)
const newImageData = ctx.createImageData(imageData)
const width = imageData.width / size
const height = imageData.height / size
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
setRGBA(imageData, newImageData, i * size, j * size, size)
}
}
}
function getRGBA(x, y) {
return ctx.getImageData(x, y, 1, 1).data
}
function setRGBA(imageData, newImageData, x, y, size) {
const color = getRGBA(x, y)
const w = newImageData.width
const h = newImageData.height
const tempData = newImageData.data
for (let n = 0; n < size; n++) {
for (let m = 0; m < size; m++) {
tempData[(w * (y + m) + x + n) * 4 + 0] = color[0]
tempData[(w * (y + m) + x + n) * 4 + 1] = color[1]
tempData[(w * (y + m) + x + n) * 4 + 2] = color[2]
tempData[(w * (y + m) + x + n) * 4 + 3] = color[3]
}
}
ctx.putImageData(newImageData, 400, 0)
}
}
}
</script>
</body>
</html>
随机获取马赛克像素
效果图

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
}
.syt {
background-color: rgba(158, 169, 203, 255);
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="400">
您的浏览器不支持canvas,请更换浏览器
</canvas>
<script>
window.onload = () => {
if (canvas.getContext) {
canvas.style.backgroundColor = 'orange'
const ctx = canvas.getContext('2d')
const image = new Image(200, 300)
image.width = 200
image.src = '../images/2.jpg'
image.onload = () => {
draw(image)
}
function draw(image) {
const size = 4
ctx.drawImage(image, 0, 0, 400, 400)
const imageData = ctx.getImageData(0, 0, 400, 400)
const newImageData = ctx.createImageData(imageData)
const width = imageData.width / size
const height = imageData.height / size
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
setRGBA(imageData, newImageData, i * size, j * size, size)
}
}
}
function getRGBA(x, y) {
return ctx.getImageData(x, y, 1, 1).data
}
function setRGBA(imageData, newImageData, x, y, size) {
const randomX = random(size)
const randomY = random(size)
const color = getRGBA(x + randomX, y + randomY)
const w = newImageData.width
const h = newImageData.height
const tempData = newImageData.data
for (let n = 0; n < size; n++) {
for (let m = 0; m < size; m++) {
tempData[(w * (y + m) + x + n) * 4 + 0] = color[0]
tempData[(w * (y + m) + x + n) * 4 + 1] = color[1]
tempData[(w * (y + m) + x + n) * 4 + 2] = color[2]
tempData[(w * (y + m) + x + n) * 4 + 3] = color[3]
}
}
ctx.putImageData(newImageData, 400, 0)
}
function random(size) {
return Math.floor(Math.random() * size)
}
}
}
</script>
</body>
</html>

浙公网安备 33010602011771号