参考:https://blog.csdn.net/sinat_33488770/article/details/119298802
像素处理 https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas
- 包含高度 × 宽度 × 4 bytes数据,索引值从0到(高度×宽度×4)-1
例如,要读取图片中位于第50行,第200列的像素的蓝色部份,你会写以下代码:
blueComponent = imageData.data[((50 * (imageData.width * 4)) + (200 * 4)) + 2];
- 根据行、列读取某像素点的R/G/B/A值的公式:
imageData.data[((50 * (imageData.width * 4)) + (200 * 4)) + 0/1/2/3];
- 你可能用会使用Uint8ClampedArray.length属性来读取像素数组的大小(以bytes为单位):
var numBytes = imageData.data.length;
颜色选择器
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = './assets/rhino.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
};
var hoveredColor = document.getElementById('hovered-color');
var selectedColor = document.getElementById('selected-color');
function pick(event, destination) {
var x = event.layerX;
var y = event.layerY;
var pixel = ctx.getImageData(x, y, 1, 1);
var data = pixel.data;
const rgba = `rgba(${data[0]}, ${data[1]}, ${data[2]}, ${data[3] / 255})`;
destination.style.background = rgba;
destination.textContent = rgba;
return rgba;
}
canvas.addEventListener('mousemove', function(event) {
pick(event, hoveredColor);
});
canvas.addEventListener('click', function(event) {
pick(event, selectedColor);
});
图片灰度和反相颜色
var img = new Image();
img.crossOrigin = 'anonymous';
img.src = './assets/rhino.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
var original = function() {
ctx.drawImage(img, 0, 0);
};
var invert = function() {
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // red
data[i + 1] = 255 - data[i + 1]; // green
data[i + 2] = 255 - data[i + 2]; // blue
}
ctx.putImageData(imageData, 0, 0);
};
var grayscale = function() {
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
var avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
data[i] = avg; // red
data[i + 1] = avg; // green
data[i + 2] = avg; // blue
}
ctx.putImageData(imageData, 0, 0);
};
const inputs = document.querySelectorAll('[name=color]');
for (const input of inputs) {
input.addEventListener("change", function(evt) {
switch (evt.target.value) {
case "inverted":
return invert();
case "grayscale":
return grayscale();
default:
return original();
}
});
}
缩放和反锯齿
<canvas id="canvas" width="300" height="227"></canvas>
<canvas id="zoom" width="300" height="227"></canvas>
<div>
<label for="smoothbtn">
<input type="checkbox" name="smoothbtn" checked="checked" id="smoothbtn">
Enable image smoothing
</label>
</div>
var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
img.onload = function() {
draw(this);
};
function draw(img) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
var zoomctx = document.getElementById('zoom').getContext('2d');
var smoothbtn = document.getElementById('smoothbtn');
var toggleSmoothing = function(event) {
zoomctx.imageSmoothingEnabled = this.checked;
zoomctx.mozImageSmoothingEnabled = this.checked;
zoomctx.webkitImageSmoothingEnabled = this.checked;
zoomctx.msImageSmoothingEnabled = this.checked;
};
smoothbtn.addEventListener('change', toggleSmoothing);
var zoom = function(event) {
var x = event.layerX;
var y = event.layerY;
zoomctx.drawImage(canvas,
Math.abs(x - 5),
Math.abs(y - 5),
10, 10,
0, 0,
200, 200);
};
canvas.addEventListener('mousemove', zoom);
}
加载龙的图片
let img = new Image()
img.src = './龙.jpg'
img.onload = () => {
draw()
}
// 把图片绘制到canvas里
const draw = () => {
const canvas = document.getElementById('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0, img.width, img.height)
// 获取像素数据
const imgData = ctx.getImageData(0, 0, img.width, img.height).data
// 拼接字符
join(imgData)
}
// 把像素数据拼接成字符
const join = (data) => {
let gap = 10
let str = ''
for (let h = 0; h < img.height; h += gap) {
str += '\n'
for (let w = 0; w < img.width; w += gap) {
str += ' '// 因为字符的高度普遍都比其宽度大,所以额外添加一个空字符平衡一下,否则最终的图形会感觉被拉高了
let pos = (h * img.width + w) * 4
let r = data[pos]
let g = data[pos + 1]
let b = data[pos + 2]
// rgb转换成yuv格式,根据y(亮度)来判断显示什么字符
let y = r * 0.299 + g * 0.578 + b * 0.114
if (y >= 190) {
// 浅色
str += ' '
} else {
// 深色
str += '#'
}
}
}
console.log(str)
}
网路图片生成
var http = require("http");
//文件处理
var fs = require("fs");
// req 路由监听空 res 上下文函数
var server = http.createServer((req, res) => {
// 公共请求头
res.writeHead(200, {
// "Content-Type": "text/html;chaset=UTF-8",
"Content-Type": "image/png",
//设置允许跨域的域名,*代表允许任意域名跨域
"Access-Control-Allow-Origin": "*",
});
// 路由监控
if (req.url == "/fang") {
res.end("fang");
} else if (req.url == "/yuan") {
res.end("yuan");
} else {
// res.end("404");
// res.end("<a href='/fang'>fang</a><br><a href='yuan'>yuan</a>");
// fs.readFile(path,’binary’, function (err, file) { })的参数多了一个’binary’,以二进制流的方式读取。
// res.write(file,’binary’); response也以二进制流的方式向浏览器输出。
fs.readFile("./sprite.png", "binary", function (err, file) {
if (err) {
console.log(err);
return;
} else {
res.write(file, "binary");
res.end();
}
});
}
});
server.listen(3000, "127.0.0.1", (res) => {
console.log("http://127.0.0.1:3000/");
});