<!-- /**
* @fileOverview 接口文档填写
*
* @module
* @author 黄尧(355350)
* @version 1.0.0
* @description:
*
*/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0" />
<title></title>
<script src="./modules/vue.min.js"></script>
<link rel="stylesheet" href="./modules/element-ui.css" />
<script src="./modules/element-ui.js"></script>
<script src="./node_modules/sortablejs/Sortable.min.js"></script>
<script src="./node_modules/vuedraggable/dist/vuedraggable.umd.min.js"></script>
<style>
body {
margin: 0;
}
#app {
width: 100vw;
height: 100vh;
}
.canvas-box {
background-color: aquamarine;
}
.color-card {
width: 1500px;
display: flex;
flex-wrap: wrap;
}
.color-item {
width: 32px;
height: 32px;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="app">
<el-row>
<el-col :span="1">
<el-upload accept="image/png, image/jpeg" action="null" :limit="1" :on-change="onChange">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-col>
<el-col :span="canvasWidth/100*2">
<canvas id="imgBeforeCanvas" class="canvas-box" :style="{width:canvasWidth,height:canvasHeight}" :width="canvasWidth" :height="canvasHeight"> </canvas>
</el-col>
<el-col :span="canvasWidth/100*2">
<canvas id="imgAfterCanvas" class="canvas-box" :style="{width:canvasWidth,height:canvasHeight}" :width="canvasWidth" :height="canvasHeight"> </canvas>
</el-col>
<el-col :span="canvasWidth/100*2">
<canvas id="imgAfterCanvas_1" class="canvas-box" :style="{width:canvasWidth,height:canvasHeight}" :width="canvasWidth" :height="canvasHeight"> </canvas>
</el-col>
</el-row>
<span>原</span>
<canvas id="imgAfterCanvas__0" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
<span>主1</span>
<canvas id="imgAfterCanvas__4" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
<span>1</span>
<canvas id="imgAfterCanvas__1" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
<span>混</span>
<canvas id="imgAfterCanvas__3" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
<span>2</span>
<canvas id="imgAfterCanvas__2" class="canvas-box" :style="{width:canvasWidth*2,height:canvasHeight*2}" :width="canvasWidth*2" :height="canvasHeight*2"> </canvas>
<div class="color-card">
<div v-for="item in colorList" :key="item" class="color-item" :style="{backgroundColor: `${getHexColor(`rgba(${item[0]},${item[1]},${item[2]},255)`)}`}"></div>
</div>
</div>
</body>
<script>
function getBase64(file) {
const reader = new FileReader()
reader.readAsDataURL(file)
return new Promise((resolve) => {
reader.addEventListener("load", () => resolve(reader.result))
})
}
function getImageData(imgBeforeCanvas, url, imgAfterCanvas__0) {
const ctx = imgBeforeCanvas.getContext("2d") // 设置在画布上绘图的环境
const ctx_0 = imgAfterCanvas__0.getContext("2d") // 设置在画布上绘图的环境
const image = new Image()
image.src = url
const w = imgBeforeCanvas.width
const h = imgBeforeCanvas.height
const w_0 = imgAfterCanvas__0.width
const h_0 = imgAfterCanvas__0.height
return new Promise((resolve) => {
image.onload = function () {
ctx.drawImage(image, 0, 0, w, h) // 将图片绘制到画布上
ctx_0.drawImage(image, 0, 0, w_0, h_0) // 将图片绘制到画布上
const imgData = ctx.getImageData(0, 0, w, h) // 获取画布上的图像像素
resolve(imgData.data) // 获取到的数据为一维数组,包含图像的RGBA四个通道数据
}
})
}
function drawImage(dom, data) {
const ctx = dom.getContext("2d")
const matrix_obj = ctx.createImageData(dom.width, dom.height)
matrix_obj.data.set(data)
ctx.putImageData(matrix_obj, 0, 0)
}
function d1tod3(data, width, height) {
const list = []
const result = []
const len = Math.ceil(data.length / 4)
// 将每一个像素点的rgba四个值组合在一起
for (let i = 0; i < len; i++) {
const start = i * 4
list.push([data[start], data[start + 1], data[start + 2], data[start + 3]])
}
//根据图形的宽和高将数据进行分类
for (let hh = 0; hh < height; hh++) {
const tmp = []
for (let ww = 0; ww < width; ww++) {
tmp.push(list[hh * width + ww])
}
result.push(tmp)
}
return result
}
function d3tod1(data) {
const result = []
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].length; j++) {
result.push(data[i][j][0], data[i][j][1], data[i][j][2], data[i][j][3])
}
}
return result
}
function colourDistanceLAB(rgb_1, rgb_2) {
let [R_1, G_1, B_1] = rgb_1
let [R_2, G_2, B_2] = rgb_2
let rmean = (R_1 + R_2) / 2
let R = R_1 - R_2
let G = G_1 - G_2
let B = B_1 - B_2
return Math.sqrt((2 + rmean / 256) * R ** 2 + 4 * G ** 2 + (2 + (255 - rmean) / 256) * B ** 2)
}
function findNearestColorOne(color, colorList) {
let result = []
let d = Infinity
colorList.forEach((item) => {
let d_ = colourDistanceLAB(item, color)
if (d_ < d) {
d = d_
result = [...item]
}
})
return result
}
function findNearestColorTwo(color, colorList) {
let result1 = []
let d1 = Infinity
let result2 = []
let d2 = Infinity
colorList.forEach((item) => {
let d_ = colourDistanceLAB(item, color)
if (d_ < d1) {
d2 = d1
result2 = [...result1]
d1 = d_
result1 = [...item]
} else if (d_ < d2) {
d2 = d_
result2 = [...item]
}
})
return [result1, result2]
}
function getHexColor(color) {
var values = color
.replace(/rgba?\(/, "")
.replace(/\)/, "")
.replace(/[\s+]/g, "")
.split(",")
var a = parseFloat(values[3] || 1),
r = Math.floor(a * parseInt(values[0]) + (1 - a) * 255),
g = Math.floor(a * parseInt(values[1]) + (1 - a) * 255),
b = Math.floor(a * parseInt(values[2]) + (1 - a) * 255)
return "#" + ("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2)
}
const colorList = [
[193, 195, 192],
[195, 183, 13],
[213, 185, 59],
[216, 186, 0],
[141, 120, 31],
[211, 109, 0],
[215, 134, 52],
[206, 155, 76],
[208, 87, 1],
[206, 151, 0],
[209, 127, 0],
[221, 73, 3],
[211, 44, 2],
[201, 21, 0],
[190, 5, 2],
[130, 15, 22],
[82, 21, 16],
[62, 27, 21],
[240, 188, 201],
[249, 175, 198],
[240, 114, 198],
[251, 137, 195],
[226, 59, 109],
[249, 90, 94],
[241, 96, 111],
[214, 34, 46],
[65, 46, 31],
[137, 191, 226],
[213, 169, 218],
[130, 61, 162],
[47, 60, 169],
[113, 59, 85],
[142, 145, 138],
[107, 107, 99],
[37, 44, 60],
[20, 24, 23],
[241, 190, 161],
[248, 194, 166],
[248, 174, 147],
[215, 185, 149],
[177, 126, 165],
[120, 78, 38],
[88, 58, 30],
[125, 91, 53],
[108, 79, 37],
[212, 233, 69],
[228, 235, 140],
[197, 241, 182],
[133, 237, 168],
[140, 235, 107],
[150, 230, 81],
[80, 216, 76],
[7, 186, 130],
[41, 131, 37],
[99, 162, 30],
[0, 162, 42],
[3, 118, 94],
[19, 59, 58],
[83, 117, 43],
[15, 87, 42],
[31, 54, 32],
[2, 73, 161],
[32, 41, 108],
[101, 209, 222],
[59, 155, 176],
[30, 128, 215],
[56, 193, 206],
[0, 147, 161],
[97, 195, 240],
[78, 178, 237],
[0, 80, 179],
[29, 152, 222],
// [255, 255, 255],
// [250, 245, 242],
// [209, 183, 160],
// [112, 77, 66],
// [184, 136, 116]
]
const vm = new Vue({
el: "#app",
data: {
colorList,
imgbase64: "",
canvasWidth: 100,
canvasHeight: 100,
d3Data: null
},
computed: {},
methods: {
async onChange(file) {
// console.log("file", file)
this.imgbase64 = await getBase64(file.raw)
// console.log("imgbase64", this.imgbase64)
// 将图像绘制到canvas并获取图像数据
const imgBeforeCanvas = document.getElementById("imgBeforeCanvas") // canvas画布
const imgAfterCanvas__0 = document.getElementById("imgAfterCanvas__0") // canvas画布
const w = imgBeforeCanvas.width
const h = imgBeforeCanvas.height
let data = await getImageData(imgBeforeCanvas, this.imgbase64, imgAfterCanvas__0)
// console.log("data", data)
// 将数据转为高维数组
let d3Data = d1tod3(data, w, h)
this.d3Data = d3Data
// console.log("d3Data", d3Data)
// 处理图像数据
// 就近单值映射
let d3DataMapOne = JSON.parse(JSON.stringify(d3Data))
let d3DataMapOne_1 = JSON.parse(JSON.stringify(d3Data))
d3Data.forEach((row, i) => {
row.forEach((item, j) => {
let [res1, res2] = findNearestColorTwo(item, colorList)
d3DataMapOne[i][j] = [...res1, 255]
d3DataMapOne_1[i][j] = [...res2, 255]
})
})
// console.log("d3DataMapOne", d3DataMapOne)
// 就近2值映射
let d3DataMapTwo1 = JSON.parse(JSON.stringify(d3Data))
let d3DataMapTwo2 = JSON.parse(JSON.stringify(d3Data))
let d3DataMapTwo3 = JSON.parse(JSON.stringify(d3Data))
let d3DataMapTwo4 = JSON.parse(JSON.stringify(d3Data))
d3Data.forEach((row, i) => {
row.forEach((item, j) => {
let [res1, res2] = findNearestColorTwo(item, colorList)
d3DataMapTwo1[i][j] = [...res1, 255]
d3DataMapTwo2[i][j] = [...res2, 255]
})
})
let d1Data__1 = []
let d1Data__2 = []
let d1Data__3 = []
let d1Data__4 = []
for (let i = 0; i < this.canvasWidth; i++) {
for (let j = 0; j < this.canvasHeight; j++) {
d1Data__1.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo1[i][j])
d1Data__2.push(...d3DataMapTwo2[i][j], ...d3DataMapTwo2[i][j])
d1Data__3.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo2[i][j])
d1Data__4.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo1[i][j])
}
for (let j = 0; j < this.canvasHeight; j++) {
d1Data__1.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo1[i][j])
d1Data__2.push(...d3DataMapTwo2[i][j], ...d3DataMapTwo2[i][j])
d1Data__3.push(...d3DataMapTwo2[i][j], ...d3DataMapTwo1[i][j])
d1Data__4.push(...d3DataMapTwo1[i][j], ...d3DataMapTwo2[i][j])
}
}
// console.log("d1Data__1", d1Data__1)
// 将高维数组转为一维数组
let d1Data = d3tod1(d3DataMapOne)
let d1Data_1 = d3tod1(d3DataMapOne_1)
// console.log("d1Data", d1Data)
// 将处理后的数据绘制到imgAfterCanvas
// const imgAfterCanvas = document.getElementById("imgAfterCanvas") // canvas画布
// drawImage(imgAfterCanvas, d1Data)
// const imgAfterCanvas_1 = document.getElementById("imgAfterCanvas_1") // canvas画布
// drawImage(imgAfterCanvas_1, d1Data_1)
const imgAfterCanvas__1 = document.getElementById("imgAfterCanvas__1") // canvas画布
drawImage(imgAfterCanvas__1, d1Data__1)
const imgAfterCanvas__2 = document.getElementById("imgAfterCanvas__2") // canvas画布
drawImage(imgAfterCanvas__2, d1Data__2)
const imgAfterCanvas__3 = document.getElementById("imgAfterCanvas__3") // canvas画布
drawImage(imgAfterCanvas__3, d1Data__3)
const imgAfterCanvas__4 = document.getElementById("imgAfterCanvas__4") // canvas画布
drawImage(imgAfterCanvas__4, d1Data__4)
}
}
})
</script>
</html>
颜色混合算法
最新推荐文章于 2024-11-09 20:38:27 发布